// Arup Guha
// 9/22/2025
// Some code to show use of bitwise operators in C

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void printBits(unsigned long long x);
unsigned long long setBitsRnd();
unsigned long long getXORHash(unsigned long long block);

int main() {

    srand(time(0));

    // long long is 64 bits...
    unsigned long long block;

    // I'll set the bits randomly here.
    block = setBitsRnd();

    // Prints the bits 8 bits at a time with a space in between.
    printBits(block);

    unsigned long long hash = getXORHash(block);
    printf("\n");

    // Print these bits.
    printBits(hash);

    return 0;
}

// Just so we can see the bits.
void printBits(unsigned long long x) {

    // Go from MSB to LSB.
    for (int i=63; i>=0; i--) {

        // Isolate bit with a bitwise and with a number with a single 1 bit.
        if (x&(1ll<<i)) printf("1");
        else printf("0");

        // So each byte is in a line.
        if (i%8 == 0) printf("\n");
    }
}

// Returns an unsigned long long with random bits.
unsigned long long setBitsRnd() {

    unsigned long long x = 0;

    // Go to each bit.
    for (int i=0; i<64; i++) {

        // Get a random number 0 or 1.
        int tmp = rand()%2;

        // If it's odd, turn this bit on.
        if (tmp)
            x |= (1ll<<i);
    }

    return x;
}

// Returns the XOR of each byte in block.
unsigned long long getXORHash(unsigned long long block) {

    // This number has it's 8 least significants on.
    unsigned long long mask = (1<<8)-1;

    unsigned long long hash = 0;

    // There are eight blocks.
    for (int i=0; i<8; i++) {

        // mask forces the value to only be the last 8 bits.
        hash ^= (mask&block);

        // Shift the block to the right by 8 bits, getting the next 8 bits in place.
        block >>= 8;
    }

    return hash;
}



