Nibble Sort

Sun, 08 Feb 2015 00:00:00 GMT

A while back, John Regehr posted the Nibble Sort Programming Contest on his blog. The objective was to write a program that sorts the 4-bit components (nibbles) of 64-bit words as fast as possible. For example, 0x42badc0ffeed00d5 should result in 0xffeedddcba542000 after sorting.

Update (July 2015): Added analyses of the two winning solutions.

My Entry

Being susceptible to nerd sniping, this problem stuck in my head and I ended up spending two Saturday afternoons trying to implement a fast solution.

The first time, I set up my timing function wrong, and GCC optimized the whole thing away. It seemed as my solution was no faster than John's reference implementation, and I gave up. Lesson 1: check the assembly to see what's going on.

Unable to let go, I returned to the problem the next weekend, fixed the timing function, and ended up with this solution:

#include <stdint.h>

uint64_t nibble_sort_word(uint64_t arg)
{
        const uint64_t ones = 0x1111111111111111ULL;
        if (arg == (arg & 0xf) * ones) {
                return arg;
        }

        uint64_t count = 0;
        for (int i = 0; i < 16; i++) {
                count += 1ULL << (4 * (arg & 0xf));
                arg >>= 4;
        }

        uint64_t mask = ~0ULL;
        uint64_t result = 0;
        for (int i = 0; i < 16; i++) {
                int n = count & 0xf;
                count >>= 4;
                result = (result & ~mask) | ((ones & mask) * i);
                mask <<= 4 * n;
        }
        return result;
}