# Bitwise operators - Hamlet for Mathematica

What is the best way to check this famous equation:

0x2b || ~0x2b == 0xff


Mathematica doesn't seem to have a handy bitwise negation operator.

The best thing I did come up was:

FromDigits[IntegerDigits[16^^2B, 2, 8]
~BitOr~(IntegerDigits[16^^2B, 2, 8] /. {1 -> 0, 0 -> 1}), 2] == 16^^FF


which is rather terse. Or:

2^^00101011~BitOr~2^^11010100 == 16^^FF


which is ok. But it's not the same.

My naive hope was that something like this would work but it doesn't:

16^^2B~BitOr~BitNot@16^^2B == 16^^FF


Which yields False and reveals that I do not understand what bitwise negation in Mathematica parlance means...

I had hoped that BitNot[16^^2B] would yield 16^^D4, but I was utterly wrong. How can you force Mathematica to use bytes? Because IntegerDigits[16^^2B,2,8] yields {0, 0, 1, 0, 1, 0, 1, 1} which is ok, but IntegerDigits[BitNot[16^^2B], 2, 8] yields {0, 0, 1, 0, 1, 1, 0, 0}.

Apparently not really a bitwise negation.

Help, tips, etc. appreciated.

EDIT:

So due to Daniel Lichtblau's answer the best result so far might be:

NOT[bits_Integer, len_Integer: 8] /; bits >= 0 && len >= 0 := BitXor[bits, 2^len - 1]
OR = BitOr

16^^2B~OR~NOT@16^^2B == 16^^FF


:) Hilarious!

EDIT 2

I'd say the BitNot should have an optional argument, if 2's-complement is wanted, defaulting to True. As such:

protected = Unprotect[BitNot];
$BitNotActive = True; Options[BitNot] = {Compl -> True, Len -> 8}; BitNot[n_Integer, OptionsPattern[]] /;$BitNotActive :=
Block[{$BitNotActive = False}, If[OptionValue[Compl], BitNot[n], BitXor[n, 2^OptionValue[Len] - 1]] ] Protect[Evaluate[protected]];  So the big question (which is actually no question at all, since it's always true...) in Mathematica would become: 16^^2B~BitOr~BitNot[16^^2B, Compl -> False] == 16^^FF  I demand overloaded operators and number representation without the "base^^" syntax! - that is the question... – cormullion Jan 24 at 15:26 Actually it is a very real (as in correctly implemented) 2's complement bitwise negation. – Daniel Lichtblau Jan 24 at 15:30 Shakespeare was obviously ahead of his time – TomD Jan 24 at 15:40 @TomD "There are more things in heaven and earth, Horatio, Than are dreamt of in your philosophy." – belisarius Jan 24 at 15:53 Once upon a time there was a (well hidden) unsigned bit complement function. In[3]:= InternalUnsignedBitNot[43,8] Out[3]= 212 In[4]:=$Version Out[4]= 5.2 for Linux (September 17, 2006) I no longer recall why it was discarded. Maybe because it was too well hidden to get any use. I think this is the first time I've seen it requested. – Daniel Lichtblau Jan 24 at 20:54
show 9 more comments

## 2 Answers

You want to complement bits based on a given length. Easy enough.

complementBits[bits_Integer, len_Integer] /; bits >= 0 && len >= 0 :=
BitXor[bits, 2^len - 1]


(If you really want to compliment them, tell them the size is much too big for them..)

Quick test.

complementBits[43, 8]

(* Out[237]= 212 *)


Getting back to the question at hand, we have

BitOr[16^^2B, complementBits[16^^2B, 8]] == 16^^FF

(* Out[238]= True *)

-
Hello @Daniel. The comment I wrote before does not show up; so again. Thank you for your answer. I knew about the xor'ing scheme, but was stuck due to the strange results with BitNot. I don't know what BitNot is good for. I knew before. But now? Grmpf... – Stefan Jan 24 at 15:52
Once upon a time, before the bitwise operator functionality was ever released in Mathematica, I implemented the version you have in mind. It was overruled (somewhat noisily, I might add) in favor of 2's complement. There are arguments to be made for either one, and 2's complement does help to preserve various bitwise identities one might wish to have. – Daniel Lichtblau Jan 24 at 15:59

As far as I can see Mathematica's result is the correct one.

[I will use a byte representation of your bits in the following, but a longer representation will work as well.]

$2B equals 00101011, which is turned into 11010100 ($D4) with a bitwise Not.

The interpretation of this bitpattern as an integer follows the usual 2's complement rules. The first bit signals that we are dealing with a negative number. IntegerDigits ignores the sign of the number (see Properties and Relations section of its doc page) so we need its absolute value. To get this, we subtract 1 (yielding 11010011) and bit negate the result to get 00101100, which is precisely what you get.

So, conclusion: the BitNot` result of the number you input is precisely what you would expect. It is the translation in a visible bit sequence that is causing your problems.

-
 I know about the 2's complement form. Believe me. What I did not expect that IntegerDigits[16^^FF, 2, 8] yields {1, 1, 1, 1, 1, 1, 1, 1}. The documentation says: "BitNot[n] turns ones into zeros and vice versa in the binary bit representation of n." And for integers that they are represented in 2's complement form. So. How to force binary bit representation? I can not help but this is weird. I'm from the C/C++ area so I did indeed expect that ~0b10101010 == 0x01010101. I don't think that Mathematica is fully correct on that matter. – Stefan Jan 24 at 17:13