/*
 Bitwise and: &
int x = 0xABCD;   // …0000 1010 1011 1100 1101
int y = 0xFF;     // …0000 0000 0000 1111 1111
int z = x & y;    // …0000 0000 0000 1100 1101 == 0xCD

Bitwise or: |
int x = 0x60;    // …0110 0000
int y = 0x3B;    // …0011 1011
int z = x | y;   // …0111 1011 == 0x7B 

Left shift: <<
int z = 0xF << 4; //shift 0xF 4 bits to the left. 0xF0

Arithmetic Right shift: >>. (fill with sign bit)
int z = 0xAB >> 4;        //shift 0xAB 4 bits right. 0xA.
int z2 = 0x81234567 >> 4; //shift a negative number right.
                                                  //0xF8123456
                                                                                                                                
Logical Right shift: >>> (fill with 0)
int z2 = 0x81234567 >> 4; //shift a negative number right.
                          //0x08123456

 */

public class BinaryIntegers {

        static int s_count = 0;
        
        public static void printValue(String label, int value) {
                //print label in 20 spaces
                System.out.printf("%d: %s\n", ++s_count, label);
                
                //print the decimal representation of value
                System.out.printf("\tDEC: %d\n", value);
                
                //print the Hexadecimal representation of value
                //Note %08X: pad up to 8 hex digits with 0s
                //  need to print the 0x
                System.out.printf("\tHEX: 0x%08X\n", value);
                
                //print the binary representation of value
                //first create it as a string
                System.out.printf("\tBIN: %s\n\n", Integer.toBinaryString(value));
        }
        
        public static void main(String[] args) {
                //a hex value
                int hex = 0xDEADBEEF;
                
                printValue("32 bit int", hex);

                //least significant 2 bytes (4 hex digits)
                //0xFFFF is 16 0's followed by 16 1's
                //&  is the bitwise and, so the result is each binary digit of hex
                //anded with each binary digit of 0xFFFF
                printValue("2 least sig. bytes", hex & 0xFFFF);
                
                //most significant 4 bytes
                //shift the value to the right, sign extended (fill in with the most significant bit)
                //this preserves negative numbers
                printValue("arith. shift right", hex >> 16);
                
                //try logical shift - no sign extensions (fill in with 0's)
                printValue("logical shift right", hex >>> 16);
                
                //The following are the same:
                // 256
                // 2 to the 8th 
                // 1 << 8 
                // 1 0000 0000  in binary
                
                //a note about div and mod, applying them to a negative value will produce
                //  a negative result
                //using div  
                printValue("AB76 div 256", 0xAB76 / 256);
                
                //using mod
                printValue("AB76 mod 256", 0xAB76 % 256);
                
                //See constants below the main
                
                //we can combine flags with bitwise or (or addition) to remember them in one value.
                int flags = IS_VALID | IS_WRITABLE;
                printValue("Flags variable", flags);
                
                //we can then check to see if a particular flag is set using bitwise and
                if((flags & IS_WRITABLE) != 0) {
                        //here is the math:
                        //writable  0100
                        //flags     0101
                        //        & 0100
                }
                
        }
        
        //using bits for multiple booleans
        //each flag is represented by a single bit in a different position
        //this allows us to combine them without changing their values
        static int IS_VALID = 1;   //1 0x1
        static int IS_READABLE = 1 << 1;   //2  0x2
        static int IS_WRITABLE = 1 << 2;  //4  0x4
        static int IS_SOMETHING_ELSE = 1 << 3;  //8  0x8
        
}