<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title type="text" xml:lang="en">might as well hack it</title>
    <link type="application/atom+xml" href="http://guilherme-pg.com" rel="self"/>
    <updated>2013-04-09T14:42:00-07:00</updated>
    <id>http://guilherme-pg.com</id>
    <author>
        <name>Guilherme P. Gonçalves</name>
    </author>
    <rights>Copyright (c) 2010-2011 Guilherme P. Gonçalves</rights>
    
    <entry>
        <title>Oblivious random sampling</title>
        <link href="http://guilherme-pg.com/2012/11/12/Oblivious-random-sampling.html"/>
        <updated>2012-11-12T00:00:00-08:00</updated>
        <id>http://guilherme-pg.com/2012/11/12/Oblivious-random-sampling/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;Here&amp;#8217;s another neat trick I picked up from &lt;a href=&quot;http://www.amazon.com/Programming-Pearls-2nd-Jon-Bentley/dp/0201657880/&quot;&gt;Programming Pearls&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How can you select one of n objects at random, when you see the objects sequentially but you don&amp;#8217;t know the value of n beforehand?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is Problem 10 of Column 12 of the book. This problem could arise, for example, when reading a file line by line to select one line randomly without storing the entire contents of the (potentially big) file in memory.&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;The solution turns out to be quite an elegant loop: simply keep track of the currently selected object, and replace it with the i-th object with probability 1/i. That is, always select the first object, then replace it with the second with probability 1/2, and replace the then-selected object with the third with probability 1/3, and so on. It is not very hard to see that the probability for a given object to remain selected until the end of this loop is 1/n, which is exaclty what we wanted.&lt;/p&gt;
&lt;p&gt;A few days ago, I caught myself in need to select k different elements randomly from a set of n elements. I immediately considered trying to generalize the algorithm above, by iterating over the set of n elements keeping track of the k elements picked so far, and replacing the (i % k)-th element that is currently selected with the i-th element traversed with probability k/i. As expected, this reduces to the algoritm above when k is 1, and unless element clashes in the same (i % k) slot cause problems (which I suspect they will, but have not proven ;) ), every element has k/n probability of being picked.&lt;/p&gt;
&lt;p&gt;After doing some research, I found a slightly simpler and (more importantly) tried-and-true solution: &lt;a href=&quot;http://en.wikipedia.org/wiki/Reservoir_sampling&quot;&gt;Reservoir Sampling&lt;/a&gt;. The main difference here is that the slot that a newly-selected element is also random. This solves any problem my algorithm sketch could have with slot clashes, and is the solution I ended up using. Interestingly, for my application, I actually have all elements for random access, but ended up using a very elegant algorithm that generalizes one for the restricted scenario in which only sequential access is possible.&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2012/11/12/Oblivious-random-sampling.html&quot;&gt;Oblivious random sampling&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>Three guys walk into a bar...</title>
        <link href="http://guilherme-pg.com/2012/05/03/Three-guys-walk-into-a-bar.html"/>
        <updated>2012-05-03T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2012/05/03/Three-guys-walk-into-a-bar/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;Three guys walk into a bar: the algorithmist, the coder and the mathematician.&lt;/p&gt;
&lt;p&gt;As they approach the counter, a short, grouchy employee with greasy hair cleans up their spots with a dirty piece of dustcloth. They sit on three adjacent stools and are greeted by their old acquaintance, the aging owner of the bar.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;dialog&quot;&gt;&amp;#8220;Howdy! What can I get you tonight?&amp;#8221;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;dialog&quot;&gt;&amp;#8220;Hello there! New guy around here?&amp;#8221;&lt;/span&gt;, says the coder, discretely pointing at the short employee.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;dialog&quot;&gt;&amp;#8220;Very observant. He is, indeed, new. And oh, so dull! He never pays any attention to what he&amp;#8217;s doing and keeps breaking glasses!&amp;#8221;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The owner of the bar then turns around and points to a shelf, where lies a row of n identical glasses. In each glass, a different number is painted with red marker, from 1 to n. He continues:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;dialog&quot;&gt;&amp;#8220;And that isn&amp;#8217;t even the worst part. After breaking a glass, he doesn&amp;#8217;t bother to mark the replacement with the same number as the one he broke. In fact, he never uses the same number, and just copies the replacement&amp;#8217;s number from another glass in the shelf.&amp;#8221;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;dialog&quot;&gt;&amp;#8220;Why is that?&amp;#8221;&lt;/span&gt;, asks the intrigued algorithmist.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;dialog&quot;&gt;&amp;#8220;No idea! And I always need to keep an eye on the shelf, looking for missing and repeated numbers in the glasses, so I can properly replace them! As if I had nothing better to do than to run an O(n²) algorithm to check the numbers every single day!&amp;#8221;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;At this point the mathematician picks up a napkin from the counter and a pen from his pocket and scribbles something. He then glances at his two friends and at the other man and proposes:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;dialog&quot;&gt;&amp;#8220;I&amp;#8217;m pretty sure we can help you come up with a better way of doing that. In fact, I think this can be done in linear time with constant space.&amp;#8221;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;He then shows the napkin to the algorithmist and the coder. The napkin reads:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There is an array containing all the integers from 1 to n in some order, except that one integer is missing and another is duplicated. Suggest an efficient algorithm for finding both numbers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;After pondering for nearly an hour, the algorithmist snatches the napkin from the mathematician&amp;#8217;s hands and writes on it for a few minutes. He then grins with satisfaction as he begins to explain his solution.&lt;/p&gt;
&lt;h3&gt;The Algorithmist&amp;#8217;s Solution&lt;/h3&gt;
&lt;p&gt;Let&amp;#8217;s start from two simpler derivatives of the original problem and work our way up to this solution.&lt;/p&gt;
&lt;p&gt;First, suppose you have an array containing all integers from 1 to n in some order, except one of them is missing. This is the same as the original problem, without the duplicated number. How can you find the missing number?&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s much easier: just take the sum S&lt;sub&gt;a&lt;/sub&gt; of all numbers in the array and compare it to S&lt;sub&gt;n&lt;/sub&gt;, the sum of the first n natural numbers. Since the first n natural numbers constitute an arithmetic progression, it follows that S&lt;sub&gt;n&lt;/sub&gt; = n(n+1)/2. The missing number is therefore just S&lt;sub&gt;n&lt;/sub&gt; &amp;#8211; S&lt;sub&gt;a&lt;/sub&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s now examine the converse problem: instead of removing a number from the array, we add one. This is the same as the original problem above, except there&amp;#8217;s only a duplicated number, and none is missing.&lt;/p&gt;
&lt;p&gt;The solution is straightforward: once again we compare S&lt;sub&gt;a&lt;/sub&gt; with S&lt;sub&gt;n&lt;/sub&gt;, and this time the duplicated number is S&lt;sub&gt;a&lt;/sub&gt; &amp;#8211; S&lt;sub&gt;n&lt;/sub&gt;.&lt;/p&gt;
&lt;p&gt;Notice how, since adding all numbers in the array takes linear time, both solutions above also take linear time and constant space.&lt;/p&gt;
&lt;p&gt;The algorithmist&amp;#8217;s solution uses a composition of the two simplified algorithms above to build a divide-and-conquer algorithm for the original, more complicated problem. Imagine the input array in the original problem can be decomposed in two halves: one containing all numbers from 1 to n/2, except one of the numbers is missing, and another containing all numbers from n/2 to n, with one duplicated. Then, finding the missing and extra numbers in the array would only be a matter of applying the simplified algorithms above to the halves of the array.&lt;/p&gt;
&lt;p&gt;But how can we do that decomposition? And how do we know which half has a missing and which has an extra number?&lt;/p&gt;
&lt;p&gt;For the splitting, we can just use a derivative of the pivoting subroutine from quicksort. Given an array of n integers from 1 to n, we can pivot around the middle value (n + 1)/2 even if such value is not in the array and expect about half the integers to fall to the left of the pivot, and the other half to fall to its right. If that property doesn&amp;#8217;t hold, that is, if one side of the array is larger than the other, then the extra element must be in the larger side and the missing element should have been in the smaller side.&lt;/p&gt;
&lt;table class=&quot;img-wrap standout&quot;&gt;
    &lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;4, 1, 3, 5, 9, 10, 8, 7, 6, 7&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td class=&quot;img-caption&quot;&gt;&amp;#8212; Numbers from 1 to 10 with 2 missing and an extra 7, pivoted around 5.5&lt;br /&gt;
&lt;br /&gt;
    Notice how the left side (4, 1, 3, 5) is smaller and adds up to 13, while we would expect 15. Likewise, the right side is larger and adds up to 47, while we expected 40.    &lt;/td&gt;&lt;tr&gt;
&lt;/table&gt;
&lt;p&gt;We may be unlucky and find out that both sides have the same size, which means both the missing and the extra integers belong in the same side. However, this also means that the other side is untainted &amp;#8212; it contains exactly half of the numbers in the range from 1 to n, so we can identify it by taking the sum of its elements and comparing it with what we expected it to be: the sum of either the upper or lower half of that range. We have thus split our array in two halves, one of which is a subproblem, in that it contains half of the numbers in the range from 1 to n, except with one missing and one duplicated, and another which can be easily identified once we have the sums of the numbers in each half. All we need to do now is recurse into the subproblem, reducing the size of our problem in half.&lt;/p&gt;
&lt;p&gt;The running time of this algorithm is described by the recurrence T(n) = T(n/2) + O(n), which can be proved to be O(n), and it uses constant space. I was actually quite sloppy in the explanation above with regard to the sizes of each &amp;#8220;half&amp;#8221; of the array, or the exact behavior of the algorithm when n is even or odd, but these issues are of minor concern and are illustrated in the implementation below, in Python:&lt;/p&gt;
&lt;style&gt;
.highlight {
height: 300px;
}
&lt;/style&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;math&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sum_arith_progression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Returns sum(n, n+1, n+2, ..., m) &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;partition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Partition a list with p as pivot value.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    Returns left_sum, right_sum, idx such that sum(l[:idx+1]) == left_sum,&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    sum(l[idx+1:]) == right_sum and all elements in l[:idx+1] are smaller&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    than or equal to p, and all elements in l[idx+2:] are greater than p.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;left_sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;right_sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;left_sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;right_sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find_extra_and_missing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Given a list of integers in the range [s, t] in which a single integer&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    has been removed and another one has been added, find the missing and the&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    extra integer.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    Returns a tuple (missing, extra).&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;left_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;expected_left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum_arith_progression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;expected_right&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum_arith_progression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;expected_p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ceil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected_p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# missing and extra are on the same side&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left_sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected_left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected_p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# extra on the left, missing on the right&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;missing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected_right&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right_sum&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left_sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected_left&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# extra on the right, missing on the left&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;missing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected_left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left_sum&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right_sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected_right&lt;/span&gt;

            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;missing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how the code implements two simple tweaks to the algorithm: we calculate the sums of the elements in each half of the array while pivoting, and the tail recursion has been converted into a loop.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;dialog&quot;&gt;&amp;#8220;That&amp;#8217;s&amp;#8230; interesting!&amp;#8221;&lt;/span&gt;, says the mathematician as the enthusiastic algorithmist finishes his explanation.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;dialog&quot;&gt;&amp;#8220;Well, yes, but a bit too convoluted for me. I have a simpler way, let me show you.&amp;#8221;&lt;/span&gt;, says the coder.&lt;/p&gt;
&lt;h3&gt;The Coder&amp;#8217;s Solution&lt;/h3&gt;
&lt;p&gt;Take Y, the &lt;span class=&quot;caps&quot;&gt;XOR&lt;/span&gt; of all numbers from 1 to n, XOR&amp;#8217;ed with the &lt;span class=&quot;caps&quot;&gt;XOR&lt;/span&gt; of all numbers in the array: Y = 1 ^ 2 ^ 3 &amp;#8230; ^ n ^ A&lt;sub&gt;1&lt;/sub&gt; ^ A&lt;sub&gt;2&lt;/sub&gt; &amp;#8230; ^ A&lt;sub&gt;n&lt;/sub&gt;.&lt;/p&gt;
&lt;p&gt;Every bit in every number that is both in the array and the range exactly once will be cleared; the result will be the &lt;span class=&quot;caps&quot;&gt;XOR&lt;/span&gt; of the missing and extra numbers: Y = missing ^ extra.&lt;/p&gt;
&lt;p&gt;This happens because all other numbers end up being XOR&amp;#8217;ed with themselves once, thus clearing their bits in the result. The missing number, however, only gets XOR&amp;#8217;ed in once, and the extra number gets XOR&amp;#8217;ed three times &amp;#8212; recall that a ^ a ^ a = 0 ^ a = a for any a, and thus the bits of the extra number are never cleared.&lt;/p&gt;
&lt;p&gt;Now, since the missing and extra numbers are different, they must differ at some bit in their binary representation. Thus Y has at least one bit set. Let the i-th bit be one of those bits. Then, all numbers in the range of 1 to n whose i-th bit is set are candidates for being the missing or extra number.&lt;/p&gt;
&lt;p&gt;We take the sum of all numbers with the i-th bit set in the range from 1 to n, and compare it with the sum of the numbers with the same property in our array. If the former is bigger, their difference is the missing number. Else, the difference (in absolute value, of course) is the extra number.&lt;/p&gt;
&lt;p&gt;Having either number, the other can be found with a mere &lt;span class=&quot;caps&quot;&gt;XOR&lt;/span&gt; with Y. For example, Y ^ missing = (missing ^ extra) ^ missing = extra ^ (missing ^ missing) = extra ^ 0 = extra. This algorithm might make a few passes over the input array and its range of values, but it is definitely linear and uses constant space as well.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;dialog&quot;&gt;&amp;#8220;And voilà!&amp;#8221;&lt;/span&gt;, exclaims the coder.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;dialog&quot;&gt;&amp;#8220;Impressive, though I still like how elegant my algorithm turned out to be&amp;#8230;&amp;#8221;&lt;/span&gt;, adds the algorithmist.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;dialog&quot;&gt;&amp;#8220;So what about you?&amp;#8221;&lt;/span&gt;, asks the coder to the mathematician.&lt;/p&gt;
&lt;h3&gt;The Mathematician&amp;#8217;s Solution&lt;/h3&gt;
&lt;p&gt;The sum of all numbers in our array minus the sum of all numbers in the range from 1 to n is of course extra &amp;#8211; missing. Now, what is the sum of the &lt;em&gt;squares&lt;/em&gt; of all numbers in our array, minus the sum of all &lt;em&gt;squares&lt;/em&gt; of the numbers in the range from 1 to n? It is extra² &amp;#8211; missing² = (extra + missing)(extra &amp;#8211; missing).&lt;/p&gt;
&lt;p&gt;So now we have extra &amp;#8211; missing, and (extra + missing)(extra &amp;#8211; missing). As you can see, we are a simple substitution away from finding both numbers.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;dialog&quot;&gt;&amp;#8220;&amp;#8230;and that&amp;#8217;s about it.&amp;#8221;&lt;/span&gt;, concludes the mathematician.&lt;/p&gt;
&lt;p&gt;Beers are handed to each of the daring problem-solvers in glasses, all with a red 8 marked on them, and the night proceeds with lighter conversations.&lt;/p&gt;
&lt;h3&gt;Credits&lt;/h3&gt;
&lt;p&gt;I found the original problem at &lt;a href=&quot;http://blog.tanyakhovanova.com/?p=402&quot;&gt;Tanya Khovanova&amp;#8217;s blog&lt;/a&gt; through Hacker News.&lt;/p&gt;
&lt;p&gt;The coder&amp;#8217;s and the mathematician&amp;#8217;s solutions were taken directly from the comments in that blog&amp;#8217;s post. The algorithmist&amp;#8217;s solution, however, is my own beast :)&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2012/05/03/Three-guys-walk-into-a-bar.html&quot;&gt;Three guys walk into a bar...&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>Sorting networks revisited</title>
        <link href="http://guilherme-pg.com/2012/03/27/Sorting-networks-revisited.html"/>
        <updated>2012-03-27T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2012/03/27/Sorting-networks-revisited/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;It&amp;#8217;s been a few months since I made a brief and practical incursion into &lt;a href=&quot;/2011/09/02/Fun-with-sorting-networks.html&quot;&gt;sorting networks&lt;/a&gt;. Little did I know at the time how rich and interesting is the theory behind those clever constructs.&lt;/p&gt;
&lt;p&gt;Fast-forward to present date and I just came across two rich resources for learning the theory that drives sorting networks: Robert Sedgewick&amp;#8217;s &lt;a href=&quot;http://www.amazon.com/Algorithms-Parts-1-4-Fundamentals-Structures/dp/0201314525/ref=sr_1_1?ie=UTF8&amp;amp;qid=1332856241&amp;amp;sr=8-1&quot;&gt;Algorithms in C&lt;/a&gt; and (wait for it) Don Knuth&amp;#8217;s &lt;a href=&quot;http://www.amazon.com/Computer-Programming-Volumes-1-4A-Boxed/dp/0321751043/ref=sr_1_1?s=books&amp;amp;ie=UTF8&amp;amp;qid=1332856265&amp;amp;sr=1-1&quot;&gt;The Art of Computer Programming&lt;/a&gt;. Upon revisit, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Sorting_network&quot;&gt;Wikipedia article&lt;/a&gt; seems to have evolved quite a bit as well.&lt;/p&gt;
&lt;p&gt;So it is time to stand on the shoulders of giants and take another look at sorting networks, this time from a more theoretical standpoint. This post is by no means intended as a complete resource for this theory &amp;#8212; rather, I&amp;#8217;m just pointing out some interesting facts about sorting networks that either helped me understand their working or just made me mumble &amp;#8220;cool!&amp;#8221; as I learned them.&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s start with a quick recap: sorting networks are representations of sorting algorithms using a network of interconnected compare-and-swap gates.&lt;/p&gt;
&lt;p&gt;For example, consider the task of sorting an array of three integers, A[1..3]. One possible way of sorting this array would be to follow the procedure below:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;A&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &amp;gt; A&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;3&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;:
    swap A&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; and A&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;A&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &amp;gt; A&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;3&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;:
    swap A&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; and A&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;3&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;A&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &amp;gt; A&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;:
    swap A&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; and A&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This algorithm can be represented (and implemented in hardware) as a network of compare-and-swap gates like the one below:&lt;/p&gt;
&lt;table class=&quot;img-wrap standout&quot;&gt;
    &lt;tr&gt;&lt;td&gt;&lt;img alt=&quot;A sorting network for three elements&quot; src=&quot;/img/sorting-network-3.png&quot; title=&quot;A sorting network for three elements&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td class=&quot;img-caption&quot;&gt;&amp;#8212; A sorting network for three elements&lt;/td&gt;&lt;tr&gt;
&lt;/table&gt;
&lt;p&gt;In the image, the horizontal lines represent wires that serve as input and output to compare-and-swap gates, the vertical lines. The upper output of a compare-and-swap gate is the smallest of its inputs, and the bottom output wire receives the largest of its inputs. The network is read left to right, and by the end the elements in A are sorted in nondecreasing order.&lt;/p&gt;
&lt;p&gt;Notice how the comparisons made by the algorithm above are the same regardless of what the input sequence looks like, that is, the sequence of comparisons is &amp;#8220;oblivious&amp;#8221;, as Knuth puts it. This algorithm is thus what Sedgewick calls a &amp;#8220;nonadaptive algorithm&amp;#8221; in the definition I quote below:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A nonadaptive sorting algorithm is one where the sequence of operations performed depends only on the number of inputs, rather than on the values of the keys.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sorting networks have the interesting property of low-level parallelism: gates that don&amp;#8217;t operate on the same inputs can often work in parallel. The efficiency of a sorting network can then be defined either in terms of its depth, the number of comparators in the longest path from an input to an output, or in terms of the number of comparator gates used to build it.&lt;/p&gt;
&lt;p&gt;But how can we make a sorting network?&lt;/p&gt;
&lt;p&gt;Other than devising them through logic (which doesn&amp;#8217;t really gets me further than very small n), there are more systematic methods and heuristics. Knuth even shows in his book a sorting network for 13 elements obtained from a genetic algorithm which &amp;#8220;bears no rhyme or reason, but it works &amp;#8212; and it&amp;#8217;s shorter than any other construction devised so far by human ratiocination&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Interestingly, we can often adapt a known algorithm to use only &lt;em&gt;cmpexch(x, y)&lt;/em&gt; instructions, which are functionally equivalent to the gates in the network above, and then translate it into a sorting network.&lt;/p&gt;
&lt;p&gt;For a recursive example, let&amp;#8217;s assume we already have a sorting network for n elements, and we want to build a sorting network for n+1 elements. One valid strategy would be to sort the n first elements with the network we already have, then insert the last element into its place, like so:&lt;/p&gt;
&lt;table class=&quot;img-wrap standout&quot;&gt;
    &lt;tr&gt;&lt;td&gt;&lt;img style=&quot;height: 400px&quot; alt=&quot;Insertion sorting network&quot; src=&quot;/img/sorting-network-4.png&quot; title=&quot;Insertion sorting network&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td class=&quot;img-caption&quot;&gt;&amp;#8212; Insertion sorting network&lt;/td&gt;&lt;tr&gt;
&lt;/table&gt;
&lt;p&gt;This strategy, as you probably have noticed, is analogous to that of &lt;a href=&quot;https://en.wikipedia.org/wiki/Insertion_sort&quot;&gt;insertion sort&lt;/a&gt;. The same transformation can be made with &lt;a href=&quot;https://en.wikipedia.org/wiki/Bubble_sort&quot;&gt;bubble sort&lt;/a&gt;, and perhaps surprisingly, the parallel versions of the networks for both algorithms are exactly the same!&lt;/p&gt;
&lt;p&gt;But the real breakthrough is due to Ken Batcher, who devised a recursive &lt;em&gt;merge&lt;/em&gt; routine using &lt;em&gt;cmpexch&lt;/em&gt; instructions that made it possible to express &lt;a href=&quot;https://en.wikipedia.org/wiki/Mergesort&quot;&gt;merge sort&lt;/a&gt; as a sorting network. The result is far from trivial and best explained by Knuth. The Wikipedia article &lt;a href=&quot;https://en.wikipedia.org/wiki/Odd-even_mergesort&quot;&gt;Batcher&amp;#8217;s odd-even mergesort&lt;/a&gt; contains an implementation in Python. This algorithm uses O(n log²n) comparators for n elements, which is not optimal, but generally good enough, especially since faster alternatives hide large constants behind the asymptotic notation and are mainly of academic interest.&lt;/p&gt;
&lt;p&gt;Finally, given a sorting network, how can we prove it is correct? Recall that the comparisons made by a sorting network are independent of the nature of the input, which may make it hard for us to argue it works. It would appear that we would need to test the network against all n! possible permutations of n input elements.&lt;/p&gt;
&lt;p&gt;However, there is a better way. The simpler method uses the zero-one principle, quoted below from Sedgewick:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Zero-One Principle: If a nonadaptive algorithm produces sorted output when the inputs are all either 0 or 1, then it does so when the inputs are arbitrary keys.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The proof for the theorem above is quite simple. A proof by contradiction can be found &lt;a href=&quot;http://serverbob.3x.ro/IA/DDU0170.html&quot;&gt;here&lt;/a&gt;, and Knuth gives an analogous proof by contrapositive.&lt;/p&gt;
&lt;p&gt;So we only really need to test the network using the 2 &lt;sup&gt;n&lt;/sup&gt; possible strings of n bits, which is a large number, but nevertheless smaller than n!.&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2012/03/27/Sorting-networks-revisited.html&quot;&gt;Sorting networks revisited&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>Highlights from PyCon US 2012 lecture videos (part 2)</title>
        <link href="http://guilherme-pg.com/2012/03/20/Highlights-from-PyCon-US-2012-lecture-videos-part-2.html"/>
        <updated>2012-03-20T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2012/03/20/Highlights-from-PyCon-US-2012-lecture-videos-part-2/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;Time for the final round of talks from PyCon 2012!&lt;/p&gt;
&lt;p&gt;In case you missed it, in the &lt;a href=&quot;/2012/03/11/Highlights-from-PyCon-US-2012-lecture-videos.html&quot;&gt;first&lt;/a&gt; of this series of posts I talked about an introductory lecture on &lt;span class=&quot;caps&quot;&gt;PDB&lt;/span&gt;, the Python debugger, a cloud hosting 101 from a noob to noobs, and a two and a half-hour demystification of some often misunderstood behavior of the Python programming language.&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Mv3xgBQJPaE&quot;&gt;Graph processing in Python&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Van Lindberg presents a lecture on applied graph theory disguised as a Python lecture. But don&amp;#8217;t think that&amp;#8217;s bad at all!&lt;/p&gt;
&lt;p&gt;The lecture consists of three studies on how graphs can model and help analyze the Python community and development process, with interesting results.&lt;/p&gt;
&lt;p&gt;First, the python-dev mailing list is modeled using a directed graph in which there&amp;#8217;s an edge between two people if one replied to a topic by the other. Using the concept of vertex &lt;a target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?v=Mv3xgBQJPaE&quot; title=&quot;Centrality on Wikipedia&quot;&gt;centrality&lt;/a&gt; to model activity, the top three contributors to the mailing list are elicited. Interestingly, although the graph clearly shows a central core of active contributors, it contains no &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Clique_%28graph_theory%29&quot; title=&quot;Clique on Wikipedia&quot;&gt;cliques&lt;/a&gt;, that is, no group of people always interact with each other.&lt;/p&gt;
&lt;p&gt;Then, a graph is used to correlate people in the mailing list with their topics of interest. Finally, another graph tracks down the different licenses used in the Python code base.&lt;/p&gt;
&lt;p&gt;I may be biased due to the fact that I happen to like graph theory, but I definitely enjoyed watching this. On the Python front, I learned a bit about &lt;a href=&quot;http://networkx.lanl.gov&quot;&gt;NetworkX&lt;/a&gt;, an impressive package for graph manipulation and analysis.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=XGF3Qu4dUqk&quot;&gt;Stepping through CPython&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Larry Hastings gives an &amp;#8220;architectural sightseeing&amp;#8221; of the internals of CPython, the reference implementation of Python, which promises to get the audience started on the path to becoming a core developer.&lt;/p&gt;
&lt;p&gt;As the presenter himself puts it, this talk is more about &amp;#8220;running&amp;#8221; than &amp;#8220;stepping&amp;#8221; through CPython due to lack of time. It glosses over several architectural aspects of CPython, from the directory structure in the source code to the bytecode interpreter, through the custom memory allocator and internal object protocols, though never with quite enough information to make them digestible for those with no previous contact with the implementation.&lt;/p&gt;
&lt;p&gt;Even so, I&amp;#8217;d recommend following this lecture closely while browsing the CPython source code for those interested in what happens under the hood. Just make sure you use ctags or similar to keep up with the fast pace in this lecture.&lt;/p&gt;
&lt;p&gt;As a curiosity, did you know CPython uses &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Computed_goto#Assigned_GOTO&quot; title=&quot;Computed goto on Wikipedia&quot;&gt;gcc&amp;#8217;s computed goto extension&lt;/a&gt; where available when interpreting bytecodes?&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=hvPYuqzTPIk&quot;&gt;Fake it til you make it: unit testing patterns with mocks and fakes&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;An overview of several techinques and tools for &lt;a href=&quot;https://en.wikipedia.org/wiki/Unit_testing&quot;&gt;unit testing&lt;/a&gt; Python code by Brian K. Jones. While aiming for an audience with intermediate familiarity with the programming language, this talk assumes little prior experience with testing techniques. Which is great &amp;#8212; testing and validation are areas I (still) know little about.&lt;/p&gt;
&lt;p&gt;This turned out to be a very enlightening talk in which you may learn a few general guidelines for writing testable code, such as creating wrapper classes around external resources and libraries so they can be easily mocked during testing, and also see a couple of real life applications of that knowledge.&lt;/p&gt;
&lt;p&gt;An interesting Python-specific technique I gathered from this talk is resorting to &lt;a href=&quot;https://en.wikipedia.org/wiki/Monkey_patching&quot;&gt;monkey patching&lt;/a&gt;, that is, run-time modification of live objects and classes, which is made very easy by the language, to mock specific subsystems while testing. This, if used sparingly, turns out to be a Pythonic replacement for &lt;a href=&quot;https://en.wikipedia.org/wiki/Dependency_injection&quot;&gt;dependency injection&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The talk also promotes the use of some very interesting tools, such as &lt;a href=&quot;http://nedbatchelder.com/code/coverage/&quot;&gt;coverage&lt;/a&gt; for measuring code coverage, and &lt;a href=&quot;http://mock.readthedocs.org/en/latest/index.html&quot;&gt;mock&lt;/a&gt;, which is even &lt;a href=&quot;http://www.python.org/dev/peps/pep-0417/&quot;&gt;making its way into the standard library&lt;/a&gt; in the Python 3 series as I write this.&lt;/p&gt;
&lt;p&gt;And that&amp;#8217;s it for now! There are, of course, several other lectures available (check &lt;a href=&quot;pyvideo.org&quot;&gt;pyvideo.org&lt;/a&gt; for that), and I&amp;#8217;ll probably watch a few more some time in the future. Let me know if I missed an important one!&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2012/03/20/Highlights-from-PyCon-US-2012-lecture-videos-part-2.html&quot;&gt;Highlights from PyCon US 2012 lecture videos (part 2)&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>Highlights from PyCon US 2012 lecture videos (part 1)</title>
        <link href="http://guilherme-pg.com/2012/03/11/Highlights-from-PyCon-US-2012-lecture-videos.html"/>
        <updated>2012-03-11T00:00:00-08:00</updated>
        <id>http://guilherme-pg.com/2012/03/11/Highlights-from-PyCon-US-2012-lecture-videos/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;This year&amp;#8217;s &lt;a href=&quot;http://us.pycon.org&quot; title=&quot;PyCon US&quot;&gt;PyCon US&lt;/a&gt;, the &amp;#8220;largest annual gathering for the community using and developing the open-source Python programming language&amp;#8221;, as the event&amp;#8217;s website puts it, featured a wide range of interesting presentations directed to people with varying degrees of familiarity with language and associated technologies.&lt;/p&gt;
&lt;p&gt;The videos for the lectures were released online a couple of days ago, so having not been able to witness the presentations first-hand, I decided to watch and comment some of those that caught my attention. And it was definitely worthwile!&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll split this into a series of posts, as there is quite a bit of material to be covered.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s start with a couple of introductory lectures and an intermediate one. The lecture titles are links to the actual videos, be sure to check them out.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=vfPtGsSJldg&quot;&gt;Introduction to &lt;span class=&quot;caps&quot;&gt;PDB&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Chris McDonough gives an introductory talk on &lt;span class=&quot;caps&quot;&gt;PDB&lt;/span&gt;, the Python Debugger.&lt;/p&gt;
&lt;p&gt;Lots of people aren&amp;#8217;t really used to the idea of a specialized tool for debugging Python code: it sometimes just sounds a lot easier to sprinkle log or print statements all around the code to track its execution and state.&lt;/p&gt;
&lt;p&gt;While this approach can be perfectly valid in some scenarios, a debugger generally provides much more powerful tools that can make a difference when tackling a really elusive bug.&lt;/p&gt;
&lt;p&gt;This lecture teaches the basics of &lt;span class=&quot;caps&quot;&gt;PDB&lt;/span&gt;, a resourceful Python debugger that shares many features with good old &lt;span class=&quot;caps&quot;&gt;GDB&lt;/span&gt;, the &lt;span class=&quot;caps&quot;&gt;GNU&lt;/span&gt; Debugger. It would be very nice for every Python programmer to at least learn the basics of &lt;span class=&quot;caps&quot;&gt;PDB&lt;/span&gt;, if only to consider sprinkling the following snippet instead of print statements in their code:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;c&quot;&gt;# some safe code here&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# load PDB prompt&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# let&amp;#39;s proceed carefully&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pdb&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pdb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_trace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# some dangerous code here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=hyzPYaAmVOc&quot;&gt;A noob speaks to noobs: your first site in the cloud&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Katie Cuningham, a Python and Django developer with zero sysadmin background, tells the tale of her first incursions into hosting a few personal sites in the cloud.&lt;/p&gt;
&lt;p&gt;An entertaining talk by a charismatic speaker, and although I didn&amp;#8217;t find her advice to be really essential, it was nice to learn about her use of &lt;a href=&quot;http://docs.fabfile.org/en/1.4.0/index.html&quot; title=&quot;Fabric&quot;&gt;Fabric&lt;/a&gt;, a promising project I hadn&amp;#8217;t known before.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Pi9NpxAvYSs&quot;&gt;Python epiphanies&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Stuart Williams gives a lecture targeted at software developers with a background in statically typed languages and some experience with Python aiming to clarify some common pitfalls and seemingly counterintuitive behavior in the language.&lt;/p&gt;
&lt;p&gt;Even though it is targeted at intermediate level developers, beginners might benefit from the fact that the lecture starts slowly and builds on basic concepts like the oppositions between variables (as in little boxes that contain values) versus namespaces (which map names to objects), global versus local scope and mutable versus immutable objects.&lt;/p&gt;
&lt;p&gt;The second half of the lecture picks up speed and briefly visits decorators before plunging into (meta) classes. The distinctions between classes and objects and bound and unbound methods are carefully explained with plenty of examples. Definitely worth watching if you&amp;#8217;re not entirely sure why the following snippet prints 4 and 6 before crashing with a TypeError:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;triplicate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;num2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;Num&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;triplicate&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;num2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;triplicate&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, the talk discusses iterators, generators and the mechanics behind for loops (consider watching if the name &amp;#8220;StopIteration&amp;#8221; doesn&amp;#8217;t ring a bell) and closes with two cute examples of how dicts may be used to blur the line between code and data.&lt;/p&gt;
&lt;p&gt;And that&amp;#8217;s it for the first part. I still have a few lectures in the watch queue, which is certainly enough for a couple more installments of this series, so check back often!&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2012/03/11/Highlights-from-PyCon-US-2012-lecture-videos.html&quot;&gt;Highlights from PyCon US 2012 lecture videos (part 1)&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>Weighty Hamming weights</title>
        <link href="http://guilherme-pg.com/2012/02/05/Weighty-Hamming-weights.html"/>
        <updated>2012-02-05T00:00:00-08:00</updated>
        <id>http://guilherme-pg.com/2012/02/05/Weighty-Hamming-weights/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;I recently got myself a copy of Jon Bentley&amp;#8217;s &lt;a alt=&quot;Programming Pearls on Amazon&quot; href=&quot;http://www.amazon.com/Programming-Pearls-2nd-Jon-Bentley/dp/0201657880/&quot;&gt;Programming Pearls&lt;/a&gt;. It&amp;#8217;s been quite an instructive reading, and I&amp;#8217;ve been trying hard to pace myself, understanding the examples and working out some of the problems at the end of each Column without rushing through the pages.&lt;/p&gt;
&lt;p&gt;Having just finished Part II of the book, which overviews several interesting principles for improving the performance of a program, from choice of algorithms and data structures to low-level code tuning, I thought I&amp;#8217;d try to apply some of these concepts in a thorough resolution of a proposed problem.&lt;/p&gt;
&lt;p&gt;The problem in question is the 7th of Column 9, which asks:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Given a very long sequence (say, billions or trillions) of bytes, how would you efficiently count the total number of one bits? (That is, how many bits are turned on in the entire sequence?)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;The count of one bits in a binary string is known as its &lt;a alt=&quot;Hamming weight on Wikipedia&quot; href=&quot;http://en.wikipedia.org/wiki/Hamming_weight&quot;&gt;Hamming weight&lt;/a&gt;, so the problem could also be stated as requiring the Hamming weight of a big string of bits.&lt;/p&gt;
&lt;p&gt;The Hamming weight of a binary string may play an important role in applications in which each bit encodes information about a distinct entity, and one wishes to count entities with a given property. For instance, given a filesystem bitmap which encodes used and free blocks as zero and one bits, respectively, the Hamming weight can be used to calculate the amount of free disk space.&lt;/p&gt;
&lt;p&gt;There are known and obscure techniques for making such calculation. In particular, the thread &lt;a alt=&quot;Best algorithm to count the number of set bits in a 32 bit integer&quot; href=&quot;http://stackoverflow.com/questions/109023/best-algorithm-to-count-the-number-of-set-bits-in-a-32-bit-integer&quot;&gt;Best algorithm to count the number of set bits in a 32-bit integer&lt;/a&gt; on Stack Overflow abounds with solutions for strings of 32 bits.&lt;/p&gt;
&lt;p&gt;I approached the problem by first creating a 2.8Gib file of random bits to serve as input for my algorithms. Then, I devised a solution using a lookup table of bit counts so as to avoid having to iterate through each of the input bits and maybe take advantage of caching for the lookup table. This is the resulting C code:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;unistd.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;fcntl.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// A lookup table, maps char values to the number of one bits in them&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v2b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;register&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BUFSIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;O_RDONLY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BUFSIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v2b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;total bits set: %lu&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;
        
            
            

            &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Basically, lines 7 to 24 define a precomputed table mapping each possible value of a byte to its Hamming weight. I then read the input file in chunks into a buffer, and for each byte in each chunk, look up its Hamming weight in the table and accumulate that value into a variable. Notice how the chunk size (&lt;span class=&quot;caps&quot;&gt;BUFSIZE&lt;/span&gt;) is intentionally left unefined in the code &amp;#8212; I&amp;#8217;ll plug the value in at compilation time.&lt;/p&gt;
&lt;p&gt;For comparison purposes, I also implemented Brian Kernighan&amp;#8217;s very elegant bit-clearing method for achieving the same purpose in the inner loop, resulting in the following code:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;fcntl.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;unistd.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;register&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BUFSIZ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;O_RDONLY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BUFSIZ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;total bits set: %lu&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;
        
            
            

            &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This method iterates through each byte of the input, and clears the less significant bit in it (with the clever expression b &amp;amp;= b &amp;#8211; 1) as long as the byte&amp;#8217;s value is not zero. The count of how many bits were cleared in that byte is of course its Hamming weight.&lt;/p&gt;
&lt;p&gt;Needless to say, both programs compute the exact same amount of one bits in my data sample. But let&amp;#8217;s have a look at their performances.&lt;/p&gt;
&lt;p&gt;One important lesson from Column 6 of the book is that performance can often be achieved by tuning the program at several different design levels, from high level algorithmic choices down to system-dependent code tweaks and hardware upgrades.&lt;/p&gt;
&lt;p&gt;For this problem, both programs above are in and of themselves algorithmic improvements over the naive approach of looping through all input bits. So in order to open a new front of attack, I chose to experiment with two lower-level tuning parameters: &lt;a alt=&quot;Loop unrolling on Wikipedia&quot; href=&quot;http://en.wikipedia.org/wiki/Loop_unrolling&quot;&gt;loop unrolling&lt;/a&gt; for the inner bit-counting loop, and input chunk size.&lt;/p&gt;
&lt;p&gt;I compiled and ran the first program above using chunk sizes of 512, 1024, 4096 (my filesystem&amp;#8217;s block size), 8192 (my system&amp;#8217;s value for &lt;span class=&quot;caps&quot;&gt;BUFSIZ&lt;/span&gt;), 12288 and 16384 bytes, with and without loop unrolling. For each test, the running time was measured three times with the shell built-in time command, the first of which on cold cache, and the other two on warm cache.&lt;/p&gt;
&lt;p&gt;The tests were conducted on a Core I3 380M notebook with 4GB &lt;span class=&quot;caps&quot;&gt;RAM&lt;/span&gt; and using gcc 4.5.3. The compilations were made using -O2 and the loop unrolling was made with the -funroll-loops compilation parameter. I didn&amp;#8217;t tweak the chunk size of the second program, but I did measure its running time with and without loop unrolling.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s see the results for the lookup table method:&lt;/p&gt;
&lt;style&gt;
.test-results-wrapper {
overflow: auto;
max-width: 700px;
padding: 0px;
}
table.test-results {
text-align: center;
border-collapse: collapse;
width: 700px;
}
table.timings {
white-space: nowrap;
}
img.bracket {
float: left;
height: 4em;
}
th {
padding: 0px 20px;
border-bottom: 1px solid black;
}
tr.norow {
border-bottom: 1px solid black;
}
tr.norow:last-child {
border: none;
}
&lt;/style&gt;
&lt;div class=&quot;test-results-wrapper standout&quot;&gt;
&lt;table class=&quot;test-results&quot;&gt;
&lt;tr&gt;
            &lt;th&gt;Chunk size (bytes)&lt;/th&gt;
            &lt;th&gt;Loop unrolling&lt;/th&gt;
            &lt;th&gt;Times (seconds, real/user/sys)&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
            &lt;td rowspan=&quot;2&quot;&gt;8&lt;/td&gt;
            &lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                &lt;tr&gt;&lt;td&gt;2m52.240s / 0m11.791s / 2m38.049s&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;2m47.847s / 0m11.893s / 2m35.125s&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;2m47.048s / 0m11.934s / 2m34.432s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;norow&quot;&gt;
        &lt;td&gt;No&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;3m30.076s / 0m12.174s / 3m15.364s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;3m19.436s / 0m12.514s / 3m5.905s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;3m18.667s / 0m12.576s / 3m5.227s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
            &lt;td rowspan=&quot;2&quot;&gt;512&lt;/td&gt;
            &lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;0m29.340s / 0m7.138s / 0m9.451s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m8.360s / 0m2.750s / 0m3.226s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m6.285s / 0m2.631s / 0m3.015s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;norow&quot;&gt;
            &lt;td&gt;No&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;0m29.654s / 0m7.075s / 0m10.383s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m5.697s / 0m2.502s / 0m3.184s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m5.636s / 0m2.559s / 0m3.067s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
            &lt;td rowspan=&quot;2&quot;&gt;1024&lt;/td&gt;
            &lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;0m37.643s / 0m5.719s / 0m4.975s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m4.230s / 0m2.517s / 0m1.706s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m4.162s / 0m2.475s / 0m1.680s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;norow&quot;&gt;
            &lt;td&gt;No&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;0m31.443s / 0m6.713s / 0m6.254s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m4.304s / 0m2.444s / 0m1.853s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m4.239s / 0m2.512s / 0m1.719s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
            &lt;td rowspan=&quot;2&quot;&gt;4096&lt;/td&gt;
            &lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;0m30.454s / 0m6.560s / 0m3.302s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.323s / 0m2.420s / 0m0.897s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.271s / 0m2.415s / 0m0.849s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;norow&quot;&gt;
            &lt;td&gt;No&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;0m30.030s / 0m6.828s / 0m3.726s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.361s / 0m2.388s / 0m0.966s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.302s / 0m2.398s / 0m0.899s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
            &lt;td rowspan=&quot;2&quot;&gt;8192&lt;/td&gt;
            &lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;0m29.580s / 0m6.805s / 0m2.963s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.193s / 0m2.364s / 0m0.822s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.124s / 0m2.389s / 0m0.729s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;norow&quot;&gt;
            &lt;td&gt;No&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;0m29.372s / 0m6.784s / 0m3.044s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.212s / 0m2.430s / 0m0.775s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.144s / 0m2.410s / 0m0.727s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
            &lt;td rowspan=&quot;2&quot;&gt;12288&lt;/td&gt;
            &lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;0m30.662s / 0m6.507s / 0m2.830s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.168s / 0m2.412s / 0m0.750s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.096s / 0m2.406s / 0m0.684s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;norow&quot;&gt;
            &lt;td&gt;No&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;0m30.096s / 0m6.564s / 0m2.961s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.149s / 0m2.430s / 0m0.713s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.091s / 0m2.422s / 0m0.662s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
            &lt;td rowspan=&quot;2&quot;&gt;16384&lt;/td&gt;
            &lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;0m29.446s / 0m6.863s / 0m2.806s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.145s / 0m2.380s / 0m0.758s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.076s / 0m2.428s / 0m0.642s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;norow&quot;&gt;
            &lt;td&gt;No&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;0m30.313s / 0m6.611s / 0m2.930s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.136s / 0m2.409s / 0m0.721s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m3.085s / 0m2.464s / 0m0.614s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;For every chunk size and loop unrolling setting, the table above contains three timing values, the top one being on cold cache and the other two on warm cache.&lt;/p&gt;
&lt;p&gt;The running times were mostly the same for all cold cache runs regardless of chunk size, with the real (wall clock) time being much greater than the sum of user and system time. This indicates that the program was largely I/O bound in these runs, which is entirely expected and rules out the effects of the other optimizations.&lt;/p&gt;
&lt;p&gt;The other runs show that the timings decreases slowly but surely as the chunk size increases. While I did expect to reach optimal performance around 4096 or maybe 8192 bytes, the fact that the run times continued to decrease after that surprised me a bit. However, the timings for large chunk sizes are pretty close to one another, so the apparent decrease might be just due to system noise.&lt;/p&gt;
&lt;p&gt;Loop unrolling did not seem to affect the running times consistently. Although it was enabled on the best run overall (3.076s with chunk size of 16384 bytes), the runner-up (3.085s with the same chunk size) is only 0.009s behind.&lt;/p&gt;
&lt;p&gt;Finally, for comparison purposes, I timed the second program above, which employs the bit-clearing method and uses chunks of size &lt;span class=&quot;caps&quot;&gt;BUFSIZ&lt;/span&gt; (8192 for me), compiled with loop unrolling, and got the following results:&lt;/p&gt;
&lt;div class=&quot;test-results-wrapper standout&quot;&gt;
&lt;table class=&quot;test-results&quot;&gt;
&lt;tr&gt;
            &lt;th&gt;Chunk size (bytes)&lt;/th&gt;
            &lt;th&gt;Loop unrolling&lt;/th&gt;
            &lt;th&gt;Times (seconds, real/user/sys)&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
            &lt;td rowspan=&quot;2&quot;&gt;8192&lt;/td&gt;
            &lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;
&lt;img class=&quot;bracket&quot; src=&quot;/img/curly.jpg&quot;/&gt;
&lt;table class=&quot;timings&quot;&gt;
                    &lt;tr&gt;&lt;td&gt;0m47.605s / 0m44.523s / 0m1.616s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m45.788s / 0m44.079s / 0m1.070s&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;0m45.554s / 0m44.077s / 0m0.948s&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Wow! This method is almost 15 times slower, and spends most of its time in user space &amp;#8212; it&amp;#8217;s &lt;span class=&quot;caps&quot;&gt;CPU&lt;/span&gt;-bound even in cold cache!&lt;/p&gt;
&lt;p&gt;The lookup table method is a lot faster, likely for making good use of the system&amp;#8217;s caching mechanism and relying on fast array indexing for computing the Hamming weights of individual bytes.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update (09/02/2012)&lt;/em&gt;: Experimenting with different data types for the bit buffer also gives interesting results. Replacing the array of unsigned chars with an array of unsigned longs (whose size matches the word size for my machine) reduces the timings for the bit-counting method to 14.425s on warm cache, of which 13.706s are spent in user space.&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2012/02/05/Weighty-Hamming-weights.html&quot;&gt;Weighty Hamming weights&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>JSON parsing with Python coroutines</title>
        <link href="http://guilherme-pg.com/2011/12/29/JSON-parsing-with-Python-coroutines.html"/>
        <updated>2011-12-29T00:00:00-08:00</updated>
        <id>http://guilherme-pg.com/2011/12/29/JSON-parsing-with-Python-coroutines/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;A while ago, I read a blog post by Python developer Eli Bendersky on &lt;a href=&quot;http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/&quot; title=&quot;Co-routines as an alternative to state machines&quot;&gt;Co-routines as an alternative to state machines&lt;/a&gt;, in which he presents evidence to support a very interesting observation quoted below:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Co-routines are to state machines what recursion is to stacks.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;which is to say, state machines can be expressed as concisely and elegantly through the use of coroutines as recursive algorithms through recursive functions (as opposed to using an explicit stack).&lt;/p&gt;
&lt;p&gt;Now, coroutines you say?&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;To quote from the Wikipedia entry:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Coroutine&quot; title=&quot;Coroutines on Wikipedia&quot;&gt;Coroutines&lt;/a&gt; are computer program components that generalize subroutines to allow multiple entry points for suspending and resuming execution at certain locations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which, in simpler terms, means a coroutine is like a function from which you may yield and resume control at arbitrary instructions &amp;#8212; &lt;em&gt;there is no longer a single entry point to the procedure expressed as a coroutine&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The emphasized statement above is probably the main argument in favor of using coroutines to implement state machines, as it makes restoring the coroutine&amp;#8217;s execution context (that is, the state in a state machine) when new input arrives much simpler, without requiring boilerplate control structures such as &lt;strong&gt;if&lt;/strong&gt; &lt;em&gt;in state 1&lt;/em&gt;: &amp;#8230; &lt;strong&gt;elif&lt;/strong&gt; &lt;em&gt;in state 2&lt;/em&gt; &amp;#8230;&lt;/p&gt;
&lt;p&gt;While coroutines don&amp;#8217;t seem to be a recent addition to Python (support for them has apparently been under discussion since 2005, when &lt;a href=&quot;http://www.python.org/dev/peps/pep-0342/&quot; title=&quot;PEP 342&quot;&gt;&lt;span class=&quot;caps&quot;&gt;PEP&lt;/span&gt; 342&lt;/a&gt;, which describes the implementation, was written), looks like they haven&amp;#8217;t achieved widespread usage, which is my way of kindly stating I had never heard of them until very recently.&lt;/p&gt;
&lt;p&gt;I won&amp;#8217;t really go into details with regard to the syntax for coroutines, as their use is quite well described in Eli Bendersky&amp;#8217;s post and references, and their abuse is cleverly documented by David Beazley&amp;#8217;s presentation &lt;a href=&quot;http://www.dabeaz.com/generators/index.html&quot; title=&quot;Generator Tricks for Systems Programmers&quot;&gt;Generator Tricks for Systems Programmers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So over the last couple of days I&amp;#8217;ve been experimenting with the ideas above in a pet project: a simple &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; parser using state machines implemented as coroutines. I must remark that this parser has little to no actual utility, as it may still be buggy and is much, much less robust and efficient than the &lt;a href=&quot;http://docs.python.org/library/json.html&quot; title=&quot;json Python module documentation&quot;&gt;json module in Python&amp;#8217;s standard library&lt;/a&gt;. Even so, I hope it might be useful for illustration and educational purposes.&lt;/p&gt;
&lt;p&gt;Basically I converted the railroad diagrams in the &lt;a href=&quot;http://json.org&quot; title=&quot;JSON.org&quot;&gt;&lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; website&lt;/a&gt; into state machines that operate on one character at a time from the input, and made a familiar loads() function on top of those to simplify parsing from a string.&lt;/p&gt;
&lt;table class=&quot;img-wrap standout&quot;&gt;
    &lt;tr&gt;&lt;td&gt;&lt;img alt=&quot;Railroad diagram for JSON strings&quot; src=&quot;http://json.org/string.gif&quot; title=&quot;Railroad diagram for JSON strings&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td class=&quot;img-caption&quot;&gt;&amp;#8212; Railroad diagram for &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; strings&lt;/td&gt;&lt;tr&gt;
&lt;/table&gt;
&lt;p&gt;As an appetite whetter, let&amp;#8217;s have a look at the string parser corresponding to the diagram above:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@coroutine&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;string_fsm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    A coroutine implementing a finite state machine for parsing JSON strings.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    Accepts the string one character at a time, and yields NOT_PARSED_YET until&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    the string has been successfully parsed.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    Once the JSON string has been parsed, yields the corresponding Python&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    string. The coroutine can&amp;#39;t be used after that.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    May raise JSONParseError on malformed strings.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    Expects data with no leading or trailing whitespace (i.e., the first and&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    last input characters should be &amp;quot;).&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOT_PARSED_YET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;JSONParseError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;JSON strings must start with a quote&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOT_PARSED_YET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c&quot;&gt;# end of string&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOT_PARSED_YET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;u&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;c&quot;&gt;# unicode 4-digit hexadecimal&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;hexval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;hexval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOT_PARSED_YET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

                &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;unichr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hexval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\b&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;f&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;n&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;
        
            
            

            &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;t&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;JSONParseError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Invalid escape character&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, there is a straightforward correspondence between the diagram and the code, with the &lt;em&gt;yield&lt;/em&gt; expressions bringing in the characters that govern state transitions.&lt;/p&gt;
&lt;p&gt;Writing this parser was a very pleasant experience that helped get my head around a convoluted construct. While I must concede that the parsing state machines do look pleasingly concise, I also felt that the use of coroutines also contributed to the complexity of the code in some aspects. For one, debugging resumable functions with multiple entry points certainly takes some time to get used to.&lt;/p&gt;
&lt;p&gt;In case anyone wants to try it, the code is in my Github page, under the name &lt;a href=&quot;https://github.com/guilherme-pg/jsonfsm&quot; title=&quot;jsonfsm on Github&quot;&gt;jsonfsm&lt;/a&gt;. The repository contains the full code for the module and a few tests, some of which were borrowed from xmms2 (thanks!). Check it out!&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2011/12/29/JSON-parsing-with-Python-coroutines.html&quot;&gt;JSON parsing with Python coroutines&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>Fun with sorting networks</title>
        <link href="http://guilherme-pg.com/2011/09/02/Fun-with-sorting-networks.html"/>
        <updated>2011-09-02T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2011/09/02/Fun-with-sorting-networks/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;A pair of interesting threads about sorting algorithms recently surfaced on Stack Overflow, bringing to discussion an exciting concept (which was entirely unknown by me): sorting networks.&lt;/p&gt;
&lt;p&gt;The first thread poses a straightforward question: &lt;a title=&quot;Fastest sort of fixed length 6 int array&quot; href=&quot;http://stackoverflow.com/questions/2786899/fastest-sort-of-fixed-length-6-int-array&quot;&gt;what is the fastest way to sort 6 integers&lt;/a&gt;? The question calls for optimized code to sort an array of integers whose size is fixed and known in advance to be 6.&lt;/p&gt;
&lt;p&gt;Experience shows that we can often sort elements a lot faster if we have some extra information about them, such as their &lt;a title=&quot;Bucket sort&quot; href=&quot;http://en.wikipedia.org/wiki/Bucket_sort&quot;&gt;distribution&lt;/a&gt; or &lt;a title=&quot;Counting sort&quot; href=&quot;http://en.wikipedia.org/wiki/Counting_sort&quot;&gt;range of values&lt;/a&gt;. So intuitively, one might expect better (albeit maybe not asymptotically better) performance from a sorting algorithm tailored for fixed-size arrays when compared to a generic version, fit for any input size.&lt;/p&gt;
&lt;p&gt;And indeed some very interesting techniques were elicited in the replies to that thread. However, one of them struck me for its simplicity and sheer speed: using a sorting network. This turned out to be faster than the generic solutions (such as insertion sort) that were posted as replies, according to the original poster&amp;#8217;s tests.&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;A brief explanation on that solution: &lt;a title=&quot;Sorting networks&quot; href=&quot;http://en.wikipedia.org/wiki/Sorting_networks&quot;&gt;sorting networks&lt;/a&gt; are abstract representations of the comparisons and swaps used to sort a fixed number of integers. They are often schematized as circuits in which input wires carry the values through pairwise compare-and-swap gates.&lt;/p&gt;
&lt;table class=&quot;img-wrap standout&quot;&gt;
    &lt;tr&gt;&lt;td style=&quot;width: 400px; height: 250px&quot;&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Sorting_network&quot;&gt;&lt;img title=&quot;Simple sorting network&quot; src=&quot;/img/sorting-network-wikipedia.png&quot; alt=&quot;A simple sorting network from Wikipedia&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td class=&quot;img-caption&quot;&gt;&amp;#8212; A simple sorting network for four elements&lt;/td&gt;&lt;tr&gt;
&lt;/table&gt;
&lt;p&gt;Sorting networks leverage the fact that, given a fixed number of integers, the comparisons needed to sort them are also fixed. That is, the same circuit for n integers can sort all inputs of that size just by comparing and swapping elements in a fixed order.&lt;/p&gt;
&lt;p&gt;I must not have been the only one puzzled by these clever constructs, since a second thread on Stack Overflow soon wondered, &lt;a title=&quot;How does a sorting network beat generic sorting algorithms&quot; href=&quot;http://stackoverflow.com/questions/3901079/how-does-a-sorting-network-beat-generic-sorting-algorithms&quot;&gt;why are sorting networks so fast&lt;/a&gt;? The answer appears to be a combination of two factors: one, sorting networks tend to make less comparisons than generic sorting algorithms, and two, the comparisons made by sorting networks are more easily parallelizable at &lt;span class=&quot;caps&quot;&gt;CPU&lt;/span&gt; level.&lt;/p&gt;
&lt;p&gt;So, in order to gain perspective on the power of that new sorting technique, I decided to run a few practical tests of my own.&lt;/p&gt;
&lt;p&gt;The methodology is simple. I implemented the &lt;a href=&quot;http://en.wikipedia.org/wiki/Quicksort&quot;&gt;quicksort&lt;/a&gt; algorithm in three forms. The first is a plain and simple version, which can be found in most textbooks. The second uses the common optimization of resorting to insertion sort for small arrays, of sizes up to eight. And the third used sorting networks for small arrays, again for sizes eight and smaller.&lt;/p&gt;
&lt;p&gt;I then ran tests for input arrays of ascending (that is, already sorted), descending (sorted in reverse), all-zeroes and random integers, of sizes doubling from 2^16 (65536) to 2^22 (4194304), and compared the average user &lt;span class=&quot;caps&quot;&gt;CPU&lt;/span&gt; times of five runs as measured with &lt;a title=&quot;time&quot; href=&quot;http://www.gnu.org/directory/time.html&quot;&gt;time&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The codes were compiled with clang 2.9, using -O1 and -O2, and ran on a 64-bit Linux system, with a Core I3 380M processor.&lt;/p&gt;
&lt;p&gt;The code I used for testing is available in my Github page, in the &lt;a title=&quot;Sorting networks test&quot; href=&quot;http://github.com/guilherme-pg/sorting-networks-test&quot;&gt;sorting-networks-test&lt;/a&gt; repository. Anyone is welcome to review and try it. I also included all raw test results in that repository.&lt;/p&gt;
&lt;p&gt;For a short summary of my results, I did not notice much difference between the insertion sort and the sorting networks versions. In fact, the former slightly outperformed the latter in almost all tests. On the bright side, both were consistently (and considerably) faster than the textbook algorithm.&lt;/p&gt;
&lt;p&gt;It may be the case that the speed-up provided by sorting networks is highly compiler/&lt;span class=&quot;caps&quot;&gt;CPU&lt;/span&gt; dependent, so I&amp;#8217;d like to see more test results on the matter before drawing a definitive conclusion. But the fact that this new technique was a match for the old and well-known quicksort + insertion sort duo in terms of performance makes it a nice addition to my toolbox anyway.&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2011/09/02/Fun-with-sorting-networks.html&quot;&gt;Fun with sorting networks&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>Further steps towards RPC</title>
        <link href="http://guilherme-pg.com/2011/08/17/Further-steps-towards-RPC.html"/>
        <updated>2011-08-17T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2011/08/17/Further-steps-towards-RPC/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;In the &lt;a href=&quot;/2011/06/26/On-to-the-client-side.html&quot; title=&quot;On to the client side...&quot;&gt;last progress update&lt;/a&gt;, I talked about how we were moving to the client side of the Service Clients implementation.&lt;/p&gt;
&lt;p&gt;Things have progressed quite a bit since then, but unfortunately that part of the project is nowhere near ready (nor will it be by the end of GSoC, which is right around the corner). Anyway, I thought I&amp;#8217;d share a bit of what I&amp;#8217;ve been working on during the past weeks of coding.&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;The lower level of what we have in mind for the client side is complete and somewhat solid. This means it is possible for clients to pass messages and replies around reliably, using the server as a bridge. The plan now is to use that capability to model the Service Client functionality.&lt;/p&gt;
&lt;p&gt;As a demonstration/proof-of-concept, we decided to brush up the very first two service clients that were conceived, &lt;em&gt;sumclient&lt;/em&gt; and &lt;em&gt;sumservice&lt;/em&gt;, and add them to the xmms2-tutorials submodule as &lt;a href=&quot;http://github.com/guilherme-pg/xmms2-tutorial/blob/master/c/tut9.c&quot; title=&quot;tut9&quot;&gt;tut9&lt;/a&gt; and &lt;a href=&quot;http://github.com/guilherme-pg/xmms2-tutorial/blob/master/c/tut10.c&quot; title=&quot;tut10&quot;&gt;tut10&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m currently working on a higher level layer on top of that, which is the actual modelling of remote procedure calls and introspection. As a general concept, we agreed on allowing service clients to define and expose three types of basic entities to other clients: namespaces, methods and broadcasts. This means offering a service will be a matter of defining one (or more (or nested)) namespaces containing methods and broadcasts which can be accessed by regular clients by sending a specially-formatted message to the service client.&lt;/p&gt;
&lt;p&gt;My work on this last week of GSoC has been on the code that defines these entities, which (I think) started to take shape around &lt;a href=&quot;http://github.com/guilherme-pg/xmms2-guilherme/commit/ba5b376c68ce550e51db295e57f2a502a4b070eb&quot;&gt;this commit&lt;/a&gt;. That code hasn&amp;#8217;t yet been reviewed and may soon suffer alterations.&lt;/p&gt;
&lt;p&gt;With that out of the way, the remaining work roughly boils down to implementing the code that articulates these data structures to offer the Service Client functionality. Basically that code should be a callback to the &lt;span class=&quot;caps&quot;&gt;MESSAGE&lt;/span&gt; broadcast (which carries client-to-client messages routed through the server) that reacts to predefined types of messages, thus being able to dispatch method calls, reply to introspection calls, record a subscription to a broadcast and so on.&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2011/08/17/Further-steps-towards-RPC.html&quot;&gt;Further steps towards RPC&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>Cyclical iterators in Python</title>
        <link href="http://guilherme-pg.com/2011/08/12/Cyclical-iterators-in-Python.html"/>
        <updated>2011-08-12T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2011/08/12/Cyclical-iterators-in-Python/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;I recently came across an amazing technique for manipulating Python iterators in a &lt;a href=&quot;http://code.activestate.com/recipes/576961-technique-for-cyclical-iteration/&quot; title=&quot;Technique for cyclical iteration&quot;&gt;recipe&lt;/a&gt; by Raymond Hettinger.&lt;/p&gt;
&lt;p&gt;The technique consists in defining an iterator as a function of itself, thus making a cyclical definition. The recipe hinges on using itertools.tee to split the to-be iterator, which is forward-referenced in a function before it is built, and feeding one (or more) of the tee&amp;#8217;d iterators into the other.&lt;/p&gt;
&lt;table class=&quot;img-wrap standout&quot;&gt;
    &lt;tr&gt;&lt;td&gt;&lt;img src=&quot;/img/ouroboros.jpg&quot; title=&quot;Ouroboros&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td class=&quot;img-caption&quot;&gt;&amp;#8212; The Ouroboros comes to mind&lt;/td&gt;&lt;tr&gt;
&lt;/table&gt;
&lt;p&gt;Bear with me, I&amp;#8217;ll explain in a moment.&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;Cyclical iterators can be quite useful when defining infinite iterators for recursive sequences. The problem solved by the recipe (generating &lt;a href=&quot;http://en.wikipedia.org/wiki/Regular_number&quot; title=&quot;Regular Numbers on Wikipedia&quot;&gt;5-smooth numbers&lt;/a&gt;) has this very recursive notion, in the sense that, given a set of these numbers, mutiplying each by 2, 3 and 5 yields a larger set of such numbers.&lt;/p&gt;
&lt;p&gt;Or, to explore the inductive side of the problem, given an iterator for the first n 5-smooth numbers, you can define a larger iterator for 5-smooth numbers by exhausting the first one and multiplying each number it outputs by 2, 3 and 5 (and eliminating duplicates).&lt;/p&gt;
&lt;p&gt;And that is exactly what the recipe does: starting with a seed value of 1 (the first 5-smooth number), it builds an iterator that swallows itself, multiplying each already-generated number by 2, 3 and 5, sorting increasingly and eliminating duplicates.&lt;/p&gt;
&lt;p&gt;I came up with this different (simpler) example while getting my head around the technique, which I&amp;#8217;ll explain in greater detail:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;operator&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;itertools&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;factorials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;delayed_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feedback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;itertools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delayed_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;seeded&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;itertools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feedback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;itertools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;seeded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;itertools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;itertools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;islice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;factorials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This returns a factorial iterator, which outputs sequentially 1!, 2!, 3! and so on. The inductive nature of the problem presents itself more clearly this time: given an iterator for the first n factorials, we can exhaust it and multiply the last value it generated by n+1 to obtain an iterator for the first n+1 factorials.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s walk by it one line at a time.&lt;/p&gt;
&lt;p&gt;Lines 1 to 3 aren&amp;#8217;t of much interest. They only make a few imports we&amp;#8217;ll need and define the function &lt;em&gt;factorials()&lt;/em&gt;, which returns the factorial iterator.&lt;/p&gt;
&lt;p&gt;Things start to get interesting in lines 04 to 07 as we define a generator inside &lt;em&gt;factorials()&lt;/em&gt; which simply iterates through some &lt;em&gt;output&lt;/em&gt; variable and yields every item in it. This is a delayed reference to &lt;em&gt;output&lt;/em&gt;: we don&amp;#8217;t want to evaluate it right now because it points to nowhere (that is, it&amp;#8217;s not defined), but we want to use it anyway. Hence, we wrap &lt;em&gt;output&lt;/em&gt; in a generator, so that it only gets evaluated when the generator is being traversed.&lt;/p&gt;
&lt;p&gt;Then on line 9 we split the iterator returned by &lt;em&gt;delayed_output()&lt;/em&gt; in two: one &lt;em&gt;result&lt;/em&gt;, which we will return from &lt;em&gt;factorials()&lt;/em&gt;, and a &lt;em&gt;feedback&lt;/em&gt; iterator, which we will feed into itself.&lt;/p&gt;
&lt;p&gt;This is the picture we have so far:&lt;/p&gt;
&lt;table class=&quot;img-wrap standout&quot;&gt;
    &lt;tr&gt;&lt;td&gt;&lt;img src=&quot;/img/line9.png&quot; title=&quot;Diagram for line 9&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td class=&quot;img-caption&quot;&gt;&amp;#8212; Diagram for line 9&lt;/td&gt;&lt;tr&gt;
&lt;/table&gt;
&lt;p&gt;Note that &lt;em&gt;output&lt;/em&gt; still points to nowhere, and if we get it to point to &lt;em&gt;feedback&lt;/em&gt; somehow, then we will be making &lt;em&gt;feedback&lt;/em&gt; indirectly point to itself.&lt;/p&gt;
&lt;p&gt;Also note that I represented &lt;em&gt;output&lt;/em&gt; twice. This emphasizes that, once we tee&amp;#8217;d the delayed reference to it, we can have &lt;em&gt;result&lt;/em&gt; and &lt;em&gt;feedback&lt;/em&gt; pointing to different parts of the iteration. More on that later.&lt;/p&gt;
&lt;p&gt;In line 10 we seed the cyclical iterator with the first value, 1!, which is just 1. We do that by defining another iterator, &lt;em&gt;seeded&lt;/em&gt;, which will first yield the seed value, then proceed with the values it finds in &lt;em&gt;feedback&lt;/em&gt;. Here&amp;#8217;s the diagram:&lt;/p&gt;
&lt;table class=&quot;img-wrap standout&quot;&gt;
    &lt;tr&gt;&lt;td&gt;&lt;img src=&quot;/img/line10.png&quot; title=&quot;Diagram for line 10&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td class=&quot;img-caption&quot;&gt;&amp;#8212; Diagram for line 10&lt;/td&gt;&lt;tr&gt;
&lt;/table&gt;
&lt;p&gt;And finally, on line 11, we define yet another iterator, which grabs one value from &lt;em&gt;seeded&lt;/em&gt;, our inductive factorial generator, and one value from the infinite sequence 1,2,3,4&amp;#8230;, multiplies them and yields the result. This is where the iterator for n factorials becomes an iterator for n+1 factorials.&lt;/p&gt;
&lt;p&gt;But wait, what is that iterator called? &lt;em&gt;output&lt;/em&gt;! The Python bites its own tail as we close the cycle and make &lt;em&gt;feedback&lt;/em&gt; point to itself indirectly. Check out the diagram:&lt;/p&gt;
&lt;table class=&quot;img-wrap standout&quot;&gt;
    &lt;tr&gt;&lt;td&gt;&lt;img src=&quot;/img/line11.png&quot; title=&quot;Diagram for line 11&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td class=&quot;img-caption&quot;&gt;&amp;#8212; Diagram for line 11&lt;/td&gt;&lt;tr&gt;
&lt;/table&gt;
&lt;p&gt;And then we return &lt;em&gt;result&lt;/em&gt;, which remained unchanged since line 09. It helps to think that &lt;em&gt;result&lt;/em&gt; always points to one value before &lt;em&gt;seeded&lt;/em&gt;. That is, every time a new factorial is requested from &lt;em&gt;result&lt;/em&gt;, &lt;em&gt;seeded&lt;/em&gt; moves one position ahead, on to the next factorial.&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2011/08/12/Cyclical-iterators-in-Python.html&quot;&gt;Cyclical iterators in Python&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>ec09bot, the time-waster Python IRC bot (and what it taught me)</title>
        <link href="http://guilherme-pg.com/2011/07/29/ec09bot-the-time-waster-Python-IRC-bot-and-what-it-taught-me.html"/>
        <updated>2011-07-29T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2011/07/29/ec09bot-the-time-waster-Python-IRC-bot-and-what-it-taught-me/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;One of the things I like the most about vacation is having the time and disposition to code weird/silly/funny ideas, which I would never bother with if it weren&amp;#8217;t for the fact that I&amp;#8217;ve been having 16 free hours every day.&lt;/p&gt;
&lt;p&gt;It is with that spirit that, once I learned that a few friends of mine (the geekiest, of course) had created an &lt;span class=&quot;caps&quot;&gt;IRC&lt;/span&gt; channel, I came up with the idea of coding a bot.&lt;/p&gt;
&lt;p&gt;Not a useful bot. Not even a smart bot. Just a funny bot.&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;To me, creating an &lt;span class=&quot;caps&quot;&gt;IRC&lt;/span&gt; bot sounds like one of these things every hacker must absolutely do once, so the task was somewhat charmful. And as with almost every other pet project/prototype of mine, I decided to use Python for extra coolness.&lt;/p&gt;
&lt;p&gt;After a little research, I came across &lt;a href=&quot;http://python-irclib.sourceforge.net/&quot; title=&quot;python-irclib&quot;&gt;python-irclib&lt;/a&gt;, which provides a framework for developing &lt;span class=&quot;caps&quot;&gt;IRC&lt;/span&gt; bots. Yay, just what I needed, specially since I had spent most of the afternoon of the previous day just to get to know the &lt;span class=&quot;caps&quot;&gt;IRC&lt;/span&gt; protocol and hand-code a vegetative-state bot that was pretty much only capable of keeping itself alive by replying to PINGs from the server. Lesson learned for code reuse.&lt;/p&gt;
&lt;p&gt;The first command to be implemented was &lt;em&gt;!batima&lt;/em&gt;, which makes the bot reply with a quote from &lt;em&gt;Feira da Fruta&lt;/em&gt;, a classic trashy humor redub of an episode of the Batman series of the 1960s.&lt;/p&gt;
&lt;p&gt;The implementation sounded pretty straightforward: given a list of such quotes, pick one at random and send it to the channel. The problem lied exactly in finding the list of quotes, which neither I nor any of my friends wanted to maintain.&lt;/p&gt;
&lt;p&gt;Luckily over the years that redub has flocked a cult of fans, and there&amp;#8217;s even a &lt;a href=&quot;http://twitter.com/#!/falasdobatima&quot; title=&quot;Falas do Bátima&quot;&gt;Twitter account&lt;/a&gt; dedicated to posting almost daily quotes from the video, all-caps for extra trashiness I presume. With some help from &lt;a href=&quot;http://code.google.com/p/python-twitter/&quot; title=&quot;python-twitter&quot;&gt;python-twitter&lt;/a&gt;, the rest was quite easy.&lt;/p&gt;
&lt;p&gt;&lt;del&gt;And along came &lt;em&gt;!chuck&lt;/em&gt;, which yields a Chuck Norris Fact taken from another twitter account.&lt;/del&gt; Update: The account in question seems to have been disabled. I&amp;#8217;ll probably re-implement the command as a fortune command.&lt;/p&gt;
&lt;p&gt;Then came the fortune-based commands, suggested by &lt;a href=&quot;http://twitter.com/ivansichmann&quot; title=&quot;Ivan&quot;&gt;Ivan&lt;/a&gt;. What better repository of funny/interesting/nonsensic quotes than the one used by the fortune Unix command? By implementing the generic functionality of grabbing a fortune cookie and sending it to the channel, we soon had Calvin &amp;amp; Hobbes, Futurama and even &lt;a href=&quot;http://en.wikipedia.org/wiki/BOFH&quot; title=&quot;Bastard Operator from Hell on Wikipedia&quot;&gt;&lt;span class=&quot;caps&quot;&gt;BOFH&lt;/span&gt;&lt;/a&gt; quotes at our disposal.&lt;/p&gt;
&lt;p&gt;And then there&amp;#8217;s the cool hack used for &lt;em&gt;!wikipedia&lt;/em&gt;, which accesses &lt;a href=&quot;http://dgl.cx/wikipedia-dns&quot; title=&quot;Wikipedia Over DNS&quot;&gt;Wikipedia Over &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt;&lt;/a&gt; using &lt;a href=&quot;http://www.dnspython.org/&quot; title=&quot;dnspython&quot;&gt;dnspython&lt;/a&gt; to grab article summaries from our favorite encyclopedia.&lt;/p&gt;
&lt;p&gt;I tried to keep the general structure of the code very modular with regard to adding/removing commands. Basically, each command is implemented as a separate module, and registered to a dispatcher class which resides in the main file, &lt;em&gt;ec09bot.py&lt;/em&gt;. The command registration code is somewhat facilitated by not having the main file import all command modules; instead, they are grouped in a single Python package. This design was somewhat inspired by the http package on newer Python versions.&lt;/p&gt;
&lt;p&gt;All in all, between new Python modules and a few design techniques, I have learned quite a bit in doing this. It has been quite fun as well. The &lt;a href=&quot;http://github.com/guilherme-pg/ec09bot&quot; title=&quot;ec09bot&quot;&gt;code of the bot&lt;/a&gt; is on Github under the &lt;span class=&quot;caps&quot;&gt;MIT&lt;/span&gt; license, anyone is welcome to try it.&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2011/07/29/ec09bot-the-time-waster-Python-IRC-bot-and-what-it-taught-me.html&quot;&gt;ec09bot, the time-waster Python IRC bot (and what it taught me)&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>On to the client side...</title>
        <link href="http://guilherme-pg.com/2011/06/26/On-to-the-client-side.html"/>
        <updated>2011-06-26T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2011/06/26/On-to-the-client-side/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;Now that the server side of the Service Clients implementation has taken shape, it&amp;#8217;s time to turn our attention to the design of the client side implementation, which is still somewhat immature.&lt;/p&gt;
&lt;p&gt;The basic idea is that, now that the server is capable of dumbly passing messages and replies among clients, we can use that capability to model the actual Service Client functionality on the client-side. In other words, we want the clients to establish a protocol for remote procedure calls and introspection with the server, unaware of what is really going on, simply forwarding messages and replies back and forth between clients.&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;Our plan for the actual implementation will require, as expected, changes to libxmmsclient, but also the development of a new library, so far called libxmmsclient-sc. The new functionality added to libxmmsclient will merely facilitate message exchanging between clients, while the actual Service Client sugar will be laid on top of that in libxmmsclient-sc.&lt;/p&gt;
&lt;p&gt;We already had some sketches for the client side of the implementation, most notably &lt;a href=&quot;http://2af7060654a0a0b9.paste.se/&quot; title=&quot;sketch by nesciens&quot;&gt;this one&lt;/a&gt; by nesciens, which gives a pretty good idea of where we are headed. Last week I published a &lt;a href=&quot;http://pastebin.com/MZ5p0Hae&quot; title=&quot;sketch by guilherme_pg&quot;&gt;sketch of my own&lt;/a&gt;, with an updated and slightly more concrete view of the implementation details now that we know what the server is capable of. It also contained a few more ideas.&lt;/p&gt;
&lt;p&gt;While we have not yet throughly discussed these sketches and turned them into a more solid idea, they do provide a good basis we can work on refining over the next weeks.&lt;/p&gt;
&lt;p&gt;One aspect of these sketches we had quite a lengthy discussion about was the alterations needed to accommodate the new message passing functionality in the asynchronous result mechanism in libxmmsclient. With valuable input from vdust, we reached a nice idea that I began implementing with &lt;a href=&quot;http://github.com/guilherme-pg/xmms2-guilherme/commit/7e9c646823ccec4b8cdabb458b79a71556ae5bf0&quot; title=&quot;new callback types&quot;&gt;this commit&lt;/a&gt;. It still needs some testing and polishing, which I will be doing in the next days.&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2011/06/26/On-to-the-client-side.html&quot;&gt;On to the client side...&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>PyExt2lib</title>
        <link href="http://guilherme-pg.com/2011/06/10/PyExt2lib.html"/>
        <updated>2011-06-10T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2011/06/10/PyExt2lib/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;I pushed a new project to Github about a week ago: &lt;a href=&quot;http://github.com/guilherme-pg/pyext2lib&quot; title=&quot;pyext2lib&quot;&gt;PyExt2lib&lt;/a&gt;, Python bindings around the ext2fslib that comes with e2fsprogs.&lt;/p&gt;
&lt;p&gt;The motivation for this project and the story behind it are quite interesting, so I though I would share them.&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;It all started with an Operating Systems class assignment in which the students (divided into pairs) were supposed to develop a tool to extract some information from filesystems, such as sizes of segments of contiguous free blocks and sizes of blocks allocated per inode, and display some of that information as histograms.&lt;/p&gt;
&lt;p&gt;No one in the class had ever come close to doing anything related, so we all started looking into how to implement that. Some attempted to use the Virtual File System layer in the kernel to no avail, while others looked up how other tools, such as dumpe2fs, did it, and came up with the idea of using ext2lib.&lt;/p&gt;
&lt;p&gt;We thus faced the challenge of learning the poorly documented &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; of a complex library we didn&amp;#8217;t even know existed before, as a prerequisite to actually starting the assignment.&lt;/p&gt;
&lt;p&gt;PyExt2lib, albeit not crucial to overcoming this problem (which required countless hours reading the e2fsprogs source code), provided a nice abstraction over the underlying library once we got the hang of it. That is, my partner and I could rapidly encapsulate chains of undocumented ext2lib &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; calls into Python code implementing the functionalities we actually needed, such as iterating over all free blocks.&lt;/p&gt;
&lt;p&gt;Using Python also helped us with post-processing the information, a task that was made quite simple using the built-in types as data structures and matplotlib for the histograms.&lt;/p&gt;
&lt;p&gt;I had already used Cython before in a patch for xmms2, liked it and wanted to learn more about it. That and the fact that GSoC may require me to use it again made it the tool of choice to develop PyExt2lib.&lt;/p&gt;
&lt;p&gt;Even though PyExt2lib is incomplete and might never get finished, and contains some plain ugly hacks, I like to think it served its purpose and taught a few things in the process.&lt;/p&gt;
&lt;p&gt;We did, after all, deliver the assignment in time, and aside from the bindings themselves, it boiled down to about 400 lines of Python that came together in a few days.&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2011/06/10/PyExt2lib.html&quot;&gt;PyExt2lib&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>It's ALIVE!</title>
        <link href="http://guilherme-pg.com/2011/06/08/Its-alive.html"/>
        <updated>2011-06-08T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2011/06/08/Its-alive/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;It&amp;#8217;s been two weeks since I began coding for GSoC, and it&amp;#8217;s time to share some of the progress we&amp;#8217;ve made. For the anxious: the courier object, as described in the last post, is already crawling on its own. I have implemented and briefly tested both methods described in the wiki, as well as a few other features to ipc.c and GenIPC.&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;My first attempt at implementing the courier object was to expose some data structures from ipc.c to courier.c and let the latter manipulate them at will. After discussing this design with the community, we settled for hiding these data structures and only exposing through new functions the bare minimum necessary for the courier to operate.&lt;/p&gt;
&lt;p&gt;That is how &lt;a href=&quot;http://github.com/guilherme-pg/xmms2-guilherme/commit/da69cca656f036c23dc37b78a35e094d61c1ac30&quot;&gt;this commit&lt;/a&gt; came to be. Since some of the new functions are mere copies of code that already existed elsewhere in the same file, they could be used instead of that code. I should add &amp;#8220;cleaning up ipc.c&amp;#8221; to my &lt;span class=&quot;caps&quot;&gt;TODO&lt;/span&gt; list.&lt;/p&gt;
&lt;p&gt;At that point I was planning on not making the courier a xmms_object_t, and have it special-cased for commands and replies in ipc.c (just like the &lt;span class=&quot;caps&quot;&gt;SIGNAL&lt;/span&gt; object). This works for the two methods described in the wiki, but would complicate things for the other methods we have in mind. So after discussing the issue with nesciens, we decided to adapt GenIPC to our needs.&lt;/p&gt;
&lt;p&gt;This means making it possible to specify that the server should not automatically send replies to clients that call a server object&amp;#8217;s method, and that it instead should leave that responsibility to the method itself.&lt;/p&gt;
&lt;p&gt;This set of changes was made in a separate branch of my repository, which has now been merged into master. &lt;a href=&quot;http://github.com/guilherme-pg/xmms2-guilherme/commit/69bc90b7f8d402188191d58d0dcb5f0020cb5458&quot;&gt;This&lt;/a&gt; is the most relevant commit, describing the changes. The other commits are fixes and cleanups both to new and old code.&lt;/p&gt;
&lt;p&gt;With that issue out of the way, I integrated the courier object to GenIPC with these &lt;a href=&quot;http://github.com/guilherme-pg/xmms2-guilherme/commit/f112d3fa32f2f68f2ab53e851ea47f062e104296&quot;&gt;two&lt;/a&gt; &lt;a href=&quot;http://github.com/guilherme-pg/xmms2-guilherme/commit/ee1f522450b2c159644c4231d43122fd55191ac3&quot;&gt;commits&lt;/a&gt;. It should now be fairly easy to implement the remaining methods we have in mind. So far, we are planning on implementing a method that returns a list of ids of connected clients, and a method for clients to consult their own id.&lt;/p&gt;
&lt;p&gt;Today I made a small breakthrough by writing a very silly but functional service client. In order to do that, I had to hack support for the courier object in libxmmsclient and main.c. I didn&amp;#8217;t commit such ugly code, but it helped me test what I already had and, after a few hours of debugging, I had &lt;em&gt;sumservice&lt;/em&gt;, the client that accepts messages containing a list of two integers from other clients, sums them and returns the result, and &lt;em&gt;sumclient&lt;/em&gt;, the client that takes two integers from the command line and sends them for summation :)&lt;/p&gt;
&lt;p&gt;Next steps: Aside from the remaining methods for the courier, I&amp;#8217;m still unsure how to integrate this new object in main.c (i.e., its initialization and destruction). Also, the code written so far still needs revision and testing, as I may (as in, probably) have screwed up refcounting and other tricky parts.&lt;/p&gt;
&lt;p&gt;See you soon!&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2011/06/08/Its-alive.html&quot;&gt;It's ALIVE!&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>The coding begins!</title>
        <link href="http://guilherme-pg.com/2011/05/24/The-coding-begins.html"/>
        <updated>2011-05-24T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2011/05/24/The-coding-begins/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;Yesterday was the official start of the GSoC program!&lt;/p&gt;
&lt;p&gt;We had some nice ideas about my proposal during the Community Bonding Period and documented them in a &lt;a href=&quot;http://xmms2.org/wiki/Summer_of_Code_2011/Service_Clients&quot; title=&quot;Service Clients wiki page&quot; target=&quot;_blank&quot;&gt;dedicated wiki page&lt;/a&gt;. And now it&amp;#8217;s time to put them to practice.&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;I started coding the server object described in the last section of the wiki page yesterday, and also made some progress today. I&amp;#8217;ll have some code to show in the next few days.&lt;/p&gt;
&lt;p&gt;And before I forget: last week I copied over the official xmms2 development repository to &lt;a href=&quot;https://github.com/guilherme-pg/xmms2-guilherme&quot; title=&quot;xmms2-guilherme&quot; target=&quot;_blank&quot;&gt;a repository of my own in Github&lt;/a&gt;, which is where my changes will end up when they are a little more mature.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll also update the wiki page with the issues I encounter and necessary clarifications as I go.&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2011/05/24/The-coding-begins.html&quot;&gt;The coding begins!&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>XChat notifications on GNOME 3</title>
        <link href="http://guilherme-pg.com/2011/05/07/XChat-notifications-on-GNOME-3.html"/>
        <updated>2011-05-07T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2011/05/07/XChat-notifications-on-GNOME-3/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;Yesterday I decided to upgrade my Gentoo system to &lt;span class=&quot;caps&quot;&gt;GNOME&lt;/span&gt; 3. It was not a painless process, although I must admit I expected worse.&lt;/p&gt;
&lt;p&gt;One of the small annoyances that issued from the migration was that I could no longer rely on a blinking XChat tray icon to warn me of new &lt;span class=&quot;caps&quot;&gt;IRC&lt;/span&gt; messages since, well, there&amp;#8217;s no immediately visible tray. Messing with the alarm settings in XChat, I came across an option to display Notification Baloons with libnotify. Thinking it might be nice to have an occasional balloon popping up with the new message text, I enabled it.&lt;/p&gt;
&lt;p&gt;It did work, but:&lt;/p&gt;
&lt;table class=&quot;img-wrap standout&quot;&gt;
    &lt;tr&gt;&lt;td&gt;&lt;img alt=&quot;So many messages!&quot; src=&quot;/img/notify-send-clutter.png&quot; title=&quot;So many messages!&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td class=&quot;img-caption&quot;&gt;&amp;#8212; So many messages!&lt;/td&gt;&lt;tr&gt;
&lt;/table&gt;
&lt;p&gt;For every message sent, not only a balloon would pop up and vanish after a few seconds, but also an icon would persist in the notification panel. The notification panel would shortly be cluttered by lots of useless icons. (Ok, so this screenshot is actually me reproducing the problem manually, and not XChat causing it, but you get the idea).&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;Looking up the problem a bit, I found out that it &lt;a href=&quot;http://bugzilla.redhat.com/show_bug.cgi?id=693207&quot;&gt;had happened before&lt;/a&gt;, and could be solved by simply spawning the notification balloon with the appropriate parameters (namely, with a new &lt;em&gt;transient&lt;/em&gt; hint set).&lt;/p&gt;
&lt;p&gt;So, by grepping the XChat 2.8.8 source code for &lt;em&gt;notify-send&lt;/em&gt;, I eventually reached the file where the magic happens, &lt;a href=&quot;http://xchat.svn.sourceforge.net/viewvc/xchat/src/fe-gtk/plugin-tray.c?view=markup&amp;amp;pathrev=1453&quot;&gt;which looked somewhat like this&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After tinkering a bit, I found out that XChat 2.8.8 first attempts to load libnotify dynamically in order to use notification balloons, and if that fails, it falls back to calling the notify-send utility. So adding the &lt;em&gt;transient&lt;/em&gt; hint would require changes in two sections of the code.&lt;/p&gt;
&lt;p&gt;And here&amp;#8217;s the &lt;a href=&quot;http://pastebin.com/CaYGKGp3&quot;&gt;diff of my modifications&lt;/a&gt;. Basically I used &lt;a href=&quot;http://developer.gnome.org/libnotify/0.7/NotifyNotification.html#notify-notification-set-hint&quot;&gt;notify_notification_set_hint&lt;/a&gt; in the code section that attempts to use libnotify and added the command line parameter described in the bug above to notify-send.&lt;/p&gt;
&lt;p&gt;After applying this and compiling, notifications no longer leave  icons in the panel, which is exactly what I wanted.&lt;/p&gt;
&lt;p&gt;I eventually found out that due to &lt;a href=&quot;http://sourceforge.net/tracker/?func=detail&amp;amp;aid=3109838&amp;amp;group_id=239&amp;amp;atid=100239&quot;&gt;some&lt;/a&gt; &lt;a href=&quot;http://sourceforge.net/tracker/?func=detail&amp;amp;aid=3280223&amp;amp;group_id=239&amp;amp;atid=100239&quot;&gt;bugs&lt;/a&gt; present in my version of XChat, the libnotify code (but not the notify-send code) always fails even before my changes have a chance to run. Well, at least I didn&amp;#8217;t break it any further.&lt;/p&gt;
&lt;p&gt;Come to think of it, I should probably have tried the latest &lt;span class=&quot;caps&quot;&gt;SVN&lt;/span&gt; version first, since it fixes several issues with that specific file. But I had my fun anyway, and will gladly upgrade when the next XChat version comes out.&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2011/05/07/XChat-notifications-on-GNOME-3.html&quot;&gt;XChat notifications on GNOME 3&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>5-minute battery monitor</title>
        <link href="http://guilherme-pg.com/2011/04/29/5-minute-battery-monitor.html"/>
        <updated>2011-04-29T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2011/04/29/5-minute-battery-monitor/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;I was left with no AC adapter for my notebook for a few hours on Tuesday.&lt;/p&gt;
&lt;p&gt;Having no battery monitor installed and being unable to install one, I was clueless about how much battery life I still had.&lt;/p&gt;
&lt;p&gt;So I did the best I could at the time: &lt;del&gt;shut down the notebook&lt;/del&gt; hacked together a very simple battery monitor by parsing the contents of &lt;code&gt;/proc/acpi/battery/BAT0/state&lt;/code&gt; and &lt;code&gt;/proc/acpi/battery/BAT0/info&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;!-- RSS summary end --&gt;&lt;/p&gt;
&lt;p&gt;And here it is, too pointless for Github, and too useful for oblivion:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; :; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;awk &lt;span class=&quot;s1&quot;&gt;&amp;#39;(NR == 5) {print $3}&amp;#39;&lt;/span&gt; /proc/acpi/battery/BAT0/state&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;awk &lt;span class=&quot;s1&quot;&gt;&amp;#39;(NR == 3) {print $4}&amp;#39;&lt;/span&gt; /proc/acpi/battery/BAT0/info&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$now&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$total&lt;/span&gt; | &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        awk &lt;span class=&quot;s1&quot;&gt;&amp;#39;{ printf(&amp;quot;\r%d/%d mWh (%.1f%%)&amp;quot;, $1, $2, 100*$1/$2) }&amp;#39;&lt;/span&gt;

    sleep 2
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A fun time-waster would be to try to convert it into a pure awk script, but that&amp;#8217;s going to have to wait.&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2011/04/29/5-minute-battery-monitor.html&quot;&gt;5-minute battery monitor&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
    <entry>
        <title>So it begins...</title>
        <link href="http://guilherme-pg.com/2011/04/27/So-it-begins.html"/>
        <updated>2011-04-27T00:00:00-07:00</updated>
        <id>http://guilherme-pg.com/2011/04/27/So-it-begins/</id>
        <summary type="html">
        
        
        
            
            

            &lt;p&gt;I have been accepted by &lt;a href=&quot;http://xmms2.org&quot;&gt;xmms2&lt;/a&gt; as a student for GSoC this year!&lt;/p&gt;
&lt;p&gt;My proposal is to implement &lt;a href=&quot;http://www.google-melange.com/gsoc/project/google/gsoc2011/guilherme_pg/14003&quot;&gt;Service Clients&lt;/a&gt;: basically, clients that can offer functionalities to other clients by exposing methods for remote calls. This is actually a long-standing idea, and there&amp;#8217;s even an incomplete implementation already.&lt;/p&gt;
&lt;p&gt;It will be very interesting to see all sorts of crazy services popping up after I&amp;#8217;m done with my project&amp;#8230;&lt;/p&gt;
&lt;p&gt;Stay tuned!&lt;/p&gt;
        

        
        &lt;em&gt;...keep reading at &lt;a href=&quot;http://guilherme-pg.com/2011/04/27/So-it-begins.html&quot;&gt;So it begins...&lt;/a&gt;&lt;/em&gt;
        </summary>
    </entry>
    
</feed>
