#include <stdio.h>

int and(int a, int b) {
	int c = 0, s = 1, ta, tb;
#define A1	ta = a; a /= 2; ta -= 2 * a; \
			tb = b; b /= 2; tb -= 2 * b; \
			c += ta * tb * s; s *= 2;
#define A4  A1 A1 A1 A1
#define A16	A4 A4 A4 A4
	A16 A16
	return c;
}

int or(int a, int b) {
	int c = 0, s = 1, ta, tb;
#define O1	ta = a; a /= 2; ta -= 2 * a; \
			tb = b; b /= 2; tb -= 2 * b; \
			c += (ta + tb - ta * tb) * s; s *= 2;
#define O4  O1 O1 O1 O1
#define O16	O4 O4 O4 O4
	O16 O16
	return c;
}

int xor(int a, int b) {
	int c = 0, s = 1, ta, tb;
#define X1	ta = a; a /= 2; ta -= 2 * a; \
			tb = b; b /= 2; tb -= 2 * b; \
			c += (ta + tb - 2 * ta * tb) * s; s *= 2;
#define X4  X1 X1 X1 X1
#define X16	X4 X4 X4 X4
	X16 X16
	return c; 
}

int not(int a) {
	return 0 - (a + 1);
}

int sla(int a, int s) {
	if (s >= 32) return 0;
	if (s >= 16) a *= 0x10000, s -= 16;
	if (s >= 8) a *= 0x100, s -= 8;
	if (s >= 4) a *= 0x10, s -= 4;
	switch (s) {
	case 3: a *= 2;
	case 2: a *= 2;
	case 1: a *= 2;
	}
	return a;
}

int sra(int a, int s) {
	if (s >= 32) return 0;
	if (s >= 16) a /= 0x10000, s -= 16;
	if (s >= 8) a /= 0x100, s -= 8;
	if (s >= 4) a /= 0x10, s -= 4;
	switch (s) {
	case 3: a /= 2;
	case 2: a /= 2;
	case 1: a /= 2;
	}
	return a;
}

int main(void) {
	
	int a = 0x123456;
	int b = 0x456789;
	
	printf( "a = %08X\n", a );
	printf( "b = %08X\n", b );
	printf( "a and b = %08X : %08X\n", a & b, and(a, b) );
	printf( "a or b = %08X : %08X\n", a | b, or(a, b) );
	printf( "a xor b = %08X : %08X\n", a ^ b, xor(a, b) );
	printf( "not a = %08X : %08X\n", ~a, not(a));
	printf( "a << 4 = %08X : %08X\n", a << 4, sla(a, 4) );
	printf( "a >> 4 = %08X : %08X\n", a >> 4, sra(a, 4) );
	printf( "a << 19 = %08X : %08X\n", a << 19, sla(a, 19) );
	printf( "a >> 13 = %08X : %08X\n", a >> 13, sra(a, 13) );
	
	return 0;
}
