InfLab3_Hemming

Run Settings
LanguageC
Language Version
Run Command
#include <stdlib.h> #include <stdio.h> #include <malloc.h> #include <math.h> #define WELCOME_MESSAGE "Demo of Hamming encoding algorithm for 2 byte word.\n" #define NOTIFY_MESSAGE "We count digit positions from right to left, from 1 to inf.\n" #define ASK_INPUT_MESSAGE "Plz, input 2 chars: " #define MESSAGES_PATTERN "%50s" #define VERBOSE void printBinary(int a, int n); //Makes Two-Byte-Word from 2 characters (bytes). unsigned short int composeTwoBytes(unsigned char c1, unsigned char c2){ return (c1 << 8) + c2; } //0 or 1 short int getBit(int a, short int n) { return (a&(1 << n)) ? 1 : 0; } //0 or 1 //n -- is control bit number, counted **FROM RIGHT** to left. //N-th actual position is 21-N; //It's hard to understand all that "20-smth", "21-smth", "smth-5", I agree. //TODO rework all to same style? short int calcControlBit(int a, short int n) { short int ret = 0; int pow2n = pow(2, n); int i = pow2n; int s; while (i <= 21) { for (s = 0; s < pow2n; s++) { if (i + s > 21) break; ret += getBit(a, 21 - (i + s) ); } i += 2 * pow2n; } return ret % 2; } //Encodes TBW to 21-bit sequence. //Also prints control bits, if VERBOSE is defined. unsigned int encodeByHemming(unsigned int a) { int tmpBit;//for some VERBOSE outputs int exta = 0; //Extended to 21 bit seq. int i = 20; int st = 0; ////At first, let's extend TBW with zeroes. while (i >= 0) { if (21-i == pow(2, st)) { //exta |= 0; //keep 0 here -- it's position of control bit st++; } else { exta |= getBit (a, i+st-5) << i; } i--; } //Now let's fill that zeroes with actual control bits. #ifdef VERBOSE printf(MESSAGES_PATTERN, "Control bits calculated while encoding are: "); #endif //VERBOSE for(st=0; st<=4; st++){ exta |= (tmpBit = calcControlBit(exta, st)) << (21 - (int) pow(2, st)); #ifdef VERBOSE printf("%d", tmpBit); #endif // VERBOSE } #ifdef VERBOSE printf("\n"); #endif // VERBOSE //here we go... return exta; } //Prints first (from right) N bits of integer. //Unsafe?.. void printBinary(int a, int n) { int i; for (i = n - 1; i >= 0; i--) { printf("%d", getBit(a, i)); } printf("\n"); } //Inverts random bit of position from 1 to countBits. //If VERBOSE is defined, prints the position, which was inverted. unsigned int duckUpABit(unsigned int a, short int countBits){ srand(a); short int i = rand()%countBits; int ret = a & ~(1 << i); ret |= (1 << i) & ~a; #ifdef VERBOSE printf(MESSAGES_PATTERN, "We just messed up position #"); printf("%d\n", i+1); #endif // VERBOSE return ret; } //Decodes 21-bit-sequence and tries to fix mistake, if there is any. //Also prints control bits and broken (as decided) position, if VERBOSE is defined unsigned int decodeByHemming(unsigned int a){ int tmpBit; //for some VERBOSE outputs int exta = a; int st; //We will need recalculation of control bits. So, while non-zero control bits can mess things up //we need to get rid of them -- turn all c-bits to zero. for(st=0; st<=4; st++){ exta &= ~(1<<21-(int)pow(2,st)); } //Now let's recalculate control bits, and remember, ones, which is not equal to gotten control bits. short int isBroken=0; //boolean int brokenPosition=0; #ifdef VERBOSE printf(MESSAGES_PATTERN, "Control bits calculated while decoding are: "); #endif // VERBOSE for(st=0; st<=4; st++){ if((tmpBit = calcControlBit(exta,st)) != getBit(a, 21 - pow(2,st))){ isBroken = 1; brokenPosition += pow(2,st); } #ifdef VERBOSE printf("%d", tmpBit); #endif // VERBOSE } #ifdef VERBOSE printf("\n"); #endif // VERBOSE //If recalculated c-bits differ from gotten, we decide, that only 1 bit is broken, and fix it. if(isBroken){ int a2 = 0; //tmp brokenPosition = 21 - brokenPosition; //yup, we count positions *FROM RIGHT*, remember #ifdef VERBOSE printf(MESSAGES_PATTERN, "Possibly, broken position is #"); printf("%d\n", brokenPosition+1); #endif // VERBOSE //Looks like some magic. Is there any simplier way to do this?.. and should I care? a2 = a & ~(1 << brokenPosition); a2 |= (1 << brokenPosition) & ~a; a = a2; } //Let's finally forget about 5 control bits, and keep just 16. short int twoByteWord = 0; int i = 20; st = 0; while (i >= 0) { if (i == 21 - pow(2, st)) { //We do not need control bits anymore; ignore. st++; } else { twoByteWord |= getBit (a, i) << i+st-5; } i--; } return twoByteWord; } //Prints character representation of TBW -- it should be clear from name ~_~ void printTBWAsChars(unsigned short int twoByteWord){ printf("%c%c\n", *((char*) &twoByteWord), * ( ((char*) &twoByteWord) + 1)); } int main(){ printf(WELCOME_MESSAGE); printf(NOTIFY_MESSAGE); printf(MESSAGES_PATTERN, ASK_INPUT_MESSAGE); int twoByteWord = composeTwoBytes(getchar(), getchar()); printf(MESSAGES_PATTERN, "Let's encode following 2-byte word: "); printBinary(twoByteWord, 16); int encoded = encodeByHemming(twoByteWord); printf(MESSAGES_PATTERN, "The encoded sequence is: "); printBinary(encoded, 21); int messed = duckUpABit(encoded, 21); printf(MESSAGES_PATTERN, "Now we have broken one bit. Sequence becomes: "); printBinary(messed, 21); int decoded = decodeByHemming(messed); printf(MESSAGES_PATTERN, "And after decoding we have: "); printBinary (decoded, 16); printf(MESSAGES_PATTERN, "Character representation is: "); printTBWAsChars(decoded); return 0; }
Editor Settings
Theme
Key bindings
Full width
Lines