binary arithmetic…ugh

Looking through the gadget source code I’ve come across a snippet that makes little sense to me:
if(((1 << P[n].Type) & (FOF_SECONDARY_LINK_TYPES)))
where we have ‘<<’ and ‘&’ as bitwise operators. This is nasty binary, another thing I have yet to learn for reasons unknown.
So let’s go through some basics shall we? First what is binary? It’s a simple code of 1s and 0s, or on & off switches. But how do those represent numbers? Well each digit within the binary is a power of two, or as Saju puts it 2^(number of trailing digits):
0001=1
0010=2
0100=4
1000=8
....
Each 0/1 is a bit, and there are 8bits to a byte. As an example we can look at a short int, which is 2bytes. The binary representation is simply 16 1s or 0s representing the number. Let’s look at some binary examples and see how this works:
0011=2+1=3
1001=8+1=9
0110=4+2=6
1000001=2^6+1=65
Now that is under control, how does the “<<” work? This is called a left shift, and basically moves everything to the left a specified number of bits. What we have is “x << y” which means shift x to the left by y bits.
1001 << 3 = 1001000 = 2^6 + 2^3 = 64 + 8 = 72
Our original problem shows that we will be shifting the binary value of 1 by P[n].Type which will range anywhere from 0-5 in gadget.
1 << 0 = 001 << 0 = 000001 = 1
1 << 1 = 001 << 1 = 000010 = 2
1 << 2 = 001 << 2 = 000100 = 4
1 << 3 = 001 << 3 = 001000 = 8
1 << 4 = 001 << 4 = 010000 = 16
1 << 5 = 001 << 5 = 100000 = 32
Typically FOF_SECONDARY_LINK_TYPE = 2^0 + 2^4 = 1 + 16 = 17, which means we are concerned with particle types 0 (gas) and 4 (stars). This brings us to our next operator, the dirty little amperstamp. This is referred to as the bitwise AND operator. From my understanding it simply compares the each BIT between the two different values and if they are both equal to 1 we have a match. So say we have (4 & 17), how does this work? Well FIRST we have to do the left bitwise shift on 1 by 4 bits:
 STARS:
 00001 << 4 = 10000

[10000 & 10001]
 10000 // 16 (STARS)
 10001 // 17
 ----------------
 10000 = 16 (MATCH)

GAS:
 00001 << 0 = 00001

[00001 & 10001]
 00001 // 1 (GAS)
 10001 // 17
 ----------------
 00001 = 1 (MATCH)
Now if we find a match, then the code continues into this if statement, otherwise the condition check fails. As a quick example, let’s perform this same operation for DM particles (Type 1):
 DM:
 00001 << 1 = 00010

[00010 & 10001]
 00010 // 2 (DM)
 10001 // 17
 ----------------
 00000 = 0 (NO MATCH)
At first this made zero sense to me, but now I think I have a much better grip on things. If I have further issues, Saju says to look at this link.