Bit Twiddling Hacks
graphics.stanford.edu
graphics.stanford.edu
http://news.ycombinator.com/item?id=2570269
http://news.ycombinator.com/item?id=513935
http://news.ycombinator.com/item?id=86419
And also:
r = y + ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1))); // min(x, y)
my code would quickly become unreadable. I could define a macro, but those are supposedly evil[1].
[1] http://www.parashift.com/c++-faq-lite/inline-functions.html#...
The value of these examples is that if you understand the underlying mechanisms behind them you can use those building blocks to construct even more complex (and extremely fast) algorithms than demonstrated at the link. Complex, high-level algorithms can be implemented using these bit hacks once you wrap your head around what they are actually doing. The caveat is that the code will be opaque for programmers that are not fluent in bit-hacking.
For most applications you won't see much performance benefit because these are micro-optimizations. If you have a small kernel that is being executed a hundred thousand or million times per second then algorithms constructed this way can be a substantial performance optimization (easily integer factor speedup, I frequently see 10x for components).
Algorithms built on bit-twiddling primitives tend to have two properties that make them particularly efficient on modern processors. First, they make very good use of superscalar CPUs, putting the parallel ALUs to work. Second, they often take branching algorithms (e.g. small tight loops, ?: operator, if statements) and convert them into branchless algorithms. If you are doing performance and latency sensitive code, this method of building algorithms is worth learning. For everyone else, it is a neat bit of computer science arcana that really delves into the nature of integers.
Also, to answer your "how much is done for you by the compiler" question, gcc has a few builtins: __builtin_clz (count leading 0 bits), __builtin_popcount (number of 1 bits), etc. but it's not nearly enough for most common bit twiddling use-cases.
gcc -S foo.c
cmp eax, ebx
cmovg eax, ebx
The compiler will likely not understand the insane bit-hack method, which is much more complicated, and thus not parse it into a simple cmov sequence. def tomorton(x,y):
x = bin(x)[2:]
lx = len(x)
y = bin(y)[2:]
ly = len(y)
L = max(lx, ly)
m = 0
for j in xrange(1, L+1):
# note: ith bit of x requires x[lx - i] since our bin numbers are big endian
xi = int(x[lx-j]) if j-1 < lx else 0
yi = int(y[ly-j]) if j-1 < ly else 0
m += 2**(2*j)*xi + 2**(2*j+1)*yi
return m/4The magic constants used in the bit-twiddling example also have a very regular derivation. Designing an algorithm that computes the correct constants for Morton Numbers of arbitrary dimensionality is pretty simple.
There is a neat generalization of this algorithm that extends it to irregular bit interleaving patterns at the cost of requiring a few more magic constants (also derivable). I once wrote a compact engine that used algorithmically generated transform constants to produce arbitrary bit interleaving patterns in an arbitrary number of dimensions via these bit-twiddling algorithms.
There were some recent submissions here about related topics like space-filling curves and secret sharing that I've looked at before. When I started looking into abstract algebra and came across finite fields I sort of laughed at the Wikipedia page mentioning right at the beginning "Finite fields are important in number theory, algebraic geometry, Galois theory, cryptography, coding theory and Quantum error correction" with each topic being linked. It's a fun way to procrastinate.
If your engine isn't part of some secret sauce I think it would be neat to study it. Unless you know of an already existing open source equivalent that's not hidden away in the corners of something like GCC?
Once you know that, you can generate any distribution you need. However, Morton numbers take advantage of a property of their bit distributions where intermediate steps never corrupt a bit that is not going to be masked off anyway. This is not true for some other bit interleaving patterns. Extending it to arbitrary patterns requires two masking operations with another magic constant at each step which protects bits that would otherwise be destroyed in the simple Morton algorithm.
Nothing like the transform engine I wrote is open source to the best of my knowledge. There is no reason I could not open source it, I just haven't. It is pretty efficient in that it can do a number of reductions and simplifications to the minimum number of steps and constants required to produce an n-dimensional interleaved result. For irregular patterns, you end up with quite a few no-op steps that can be eliminated; for regular patterns you can reuse steps, saving memory. I'll probably write it up and put it on the web at some point.
But seriously, I'm going to crawl through this and see if there is anything that can speed up some drawing code I have. Very nice!
c = ((((c - 0x3f800000) >> r) + 0x3f800000) >> 23) - 127;
in production code I would be sad.
I think this story is relevant: http://www.folklore.org/StoryView.py?project=Macintosh&s...
Think of all of the time software wastes in people's lives by being bloated and inefficient.
In Java, for example, the default HashMap implementation [0] uses a while loop to compute the capacity of the array it will use as storage. Using the next highest power of two algorithm in the page listed is faster than this loop. Imagine if every JVM was microseconds faster every time a HashMap was allocated or resized. On one server, computer, or phone it's meaningless. On hundreds of millions of phones phones, PCs, and servers that adds up to meaningful amounts of time and energy.
[0] http://www.docjar.com/html/api/java/util/HashMap.java.html
How I miss the RIME/RelayNet C language forums...