Low Level Bit Hacks You Must Know
catonmat.net
catonmat.net
bitvec read_nbits (unsigned int count, bitstream input);
bool write_nbits (unsigned int count,bitvec bits,
bitstream output);
Then add a multirecord I/O. That is, read a record of bitvecs, each N bits wide, where the length is not given but encoded in the bitstream in this manner: read a bitvec record of N bits, if the high-bit is set (take it in whatever endian you like), read another record and repeat, if the high bit is not set, return whatever you read thus far.Then add the ability to return the bitvec records as single integers (bignums even) both signed and unsigned, taking them in this manner. If the bitvecs are unsigned, each record contributes its 7 least significant bits, and the high bit is dropped. Taking the bit on either end of the first record as the most signficant, iterate over the rest and shift and OR according to your endian needs to construct an integer from the sum of all the bits.
When I first did this exercise, I was very close to gouging my own eye-balls out, but after I did it, I started to think of bits as something very natural, and not to be feared.
let nthbit (bitContainer:'T) nth : bool = (bitContainer &&& ((1 :> 'T) <<<nth))
let bitstream (bitContainerSeq:seq<'T>) : seq<bool> =
let sz = sizeof<'T>
bitContainerSeq
|> Seq.map (fun b -> [0..sz]
|> nthbit b
|> Seq.ofArray )
|> Seq.concat
I think that should do it unfortunatley I'm away from an F# compilerAre you sure you're decoding bits from an octet stream (normal 8-bit bytes) and not using logical booleans? I ask this because I don't see any bit-manipulation operators, except maybe for "1 :> 'T" which looks like the SML module type casting, but I could be wrong.
bitstream turns a sequence of integer types into a sequence of bits.
So if you wanted to turn a stream into bits you'd do something like the following.
new System.IO.FileStream('foo.txt')
|> Seq.unfold (fun s -> (s , match s.read with
| -1 -> None
| x -> Some(x)))
|> bitstream
I just realized that the bitstream function is unnecessary and you could instead write let bits (bitContainer:'T) : seq<bool> =
[0..(sizeof<'T>*8)]
|> Seq.ofArray
|> Seq.map (fun nth -> (bitContainer &&& ((1 :> 'T) <<<nth))
And change the above code to: new System.IO.FileStream('foo.txt')
|> Seq.unfold (fun s -> (s , match s.read with
| -1 -> None
| x -> Some(x)))
|> Seq.map bits
|> Seq.concat let bitsToBitContainer (s:seq<bool>) : seq<'T> =
let sz = sizeof<'T>*8
s
|> Seq.scan (fun (i,n) x -> (i++,(n<<<1)|||(x&&&1)) (0,0)
|> Seq.filter (fun (i,n) -> i = sz)
|> Seq.map (fun (i,n) -> n)* if ((x & 1) == 0) performs same as, if ((x % 2) == 0)
* if (x & (1<<n)) same as, if (x% (pow(2,n)))
so on.. on the other hand, i find bit operations really handy when the variables in question are to be treated as separate bits than normal base-10..
Take x = 2 and n = 1
x & (1 << n) = 0b10 & 0b10 = 0b10
x % pow(2, n) = 2 % 2 = 0 = 0b0
0b0 /= 0b10
fwiw, you were actually looking for (x & ((1 << n) - 1)) = (x % pow(2, n))That aside, you're absolutely right. Using bit ops is almost always a bad idea. It turns a simple store (to a byte-addressed memory address) into a read, manipulate, and store (to a bit within a byte-addressed memory address) which can have pretty bad side affects in any concurrent environment.
int mask = v >> sizeof(int) * CHAR_BIT - 1;
unsigned int r = (v ^ mask) - mask;
can be granted a patent (http://graphics.stanford.edu/~seander/bithacks.html#IntegerA...). #define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))1. Don't be clever in our code base. Use a temp variable. 2. There's various dumb tricks with XOR, and possibly add/subtract if overflows don't break. 3. A sequence of several instructions where each of them requires the result of the previous one may not execute particularly fast on modern processors. Instruction/cycle counts -- like 3 -- are great when there's no pipeline and no cache, but otherwise pretty much useless. 4. The things you're swapping might be local variables, and when the compiler has -O <anything> specified, local variables start getting weird, and "swap" can sometimes be done in zero instructions, namely by the compiler noting that they have now been swapped and using the other one for the rest of the basic block. (or further dominated basic blocks for that matter) 5. If the things you're swapping are in main memory, or even if it's not in L1, you're going to be incurring a cost much greater than the temporary use of a register. (and, if you don't know where they are and it might be main memory, this might dominate the average runtime)
The answer is definitely not "three xors".
int x, y;
...
SWAP(x, y);
foo(x, y);
becomes int x, y;
...
foo(y, x);
(naturally, this is why I still eagerly await the arrival of a C compiler that has macros with LISP power)I don't know how every compiler works, but if you use Clang (or anything LLVM-based), it converts everything to Single Static Assignment (SSA) form:
int x1 = 42, y1 = 666;
...
int tmp = x1; x2 = y1; y2 = tmp; // SWAP(x, y)
foo(x2, y2);
In SSA form, the value of a variable does not change, so it ends up creating a bunch of "imaginary" variables to hold intermediate values. From there, it does optimizations, then figures out how best to allocate registers, and what needs to be stack-allocated.http://chaos-pp.cvs.sourceforge.net/chaos-pp/order-pp/exampl...
But I do not envy the poor soul who would have to maintain all this cleverness.
The very best candidates add: Because it's tricky, hard to read, limited in scope, and usually you can avoid swapping variables by changing their usage downstream. Besides, the best compilers will sort it out for you if you write it clearly and cleanly.
When I interview it's not the answers I listen to, it's the knowledge they expose, not of programming per se, but of good practices in programming.
[1] http://www.amazon.com/Hackers-Delight-Henry-S-Warren/dp/0201...
Now it finally gets more interesting!!! Bit hacks #1 - #5 were kind of boring to be honest.
Does anybody know a practical use case for that? I have personally never encountered a situation were I needed to manipulate the right most 1-bit.
Otherwise it's a nice introduction to bit hacking.
That's the context I learned this trick in. It's used in the Embarcadero (ex-Borland) compilers (Delphi, C++, etc.).
while flags!=0:
right_most = flags & (-flags)
process(right_most)
flags &= ~right_mostOther's have already mentioned but for real hacks in the unintuitive sense, check out Hacker's Delight and http://graphics.stanford.edu/~seander/bithacks.html.
Today embedded systems generally run Linux. You get to write a bit of assembly language code in your bootloader, and then it's just bog standard Unix programming. It's even likely that you'll be doing most of your coding in a scripting language, although it's more likely to be Lua than Ruby...
The fun thing about embedded is that since everything is done as a result of interrupts or clock signals it's all the joys of multitasking without a threading library.
I just got handed a project where the 'app' was just main() { while(1) {} } ! Everything happens as the result of functions that get magically called when certain bit patterns appear
The intersection of tricks on all those sites is quite large but on every one of them there's something you haven't seen before.
By the way if you like to wrap your mind around such tricks you might also find some gems here: http://www.azillionmonkeys.com/qed/asmexample.html