]> git.sesse.net Git - hamming/blob - hamming32.c
fb53e3b2e9dfa48c0f908ba304092f56b44ccc9a
[hamming] / hamming32.c
1 #include <stdio.h>
2
3 #define DATA_BITS    26
4 #define PARITY_BITS  6
5 #define EXTRA_BIT_POSITION (PARITY_BITS - 1)
6 #define CODE_BITS    (DATA_BITS + PARITY_BITS)
7 #define NUM_DATA_WORDS (1 << DATA_BITS)
8
9 /* 
10  * Needed since we store all the parity at the end of the word, not at the expected
11  * power-of-two bit positions.
12  */
13 unsigned char permutation_table[CODE_BITS] = {
14         0, 5, 4, 31, 3, 30, 29, 28, 2, 27, 26, 25, 24, 23, 22, 21, 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6
15 };
16
17 unsigned find_parity_32(unsigned data)
18 {
19         data = (data >> 16) ^ data;
20         data = (data >> 8) ^ data;
21         data = (data >> 4) ^ data;
22         data = (data >> 2) ^ data;
23         data = (data >> 1) ^ data;
24         return (data & 1);
25 }
26
27 unsigned generate_parity(unsigned data)
28 {
29         unsigned parity1 = find_parity_32(data & 0x036ad555);
30         unsigned parity2 = find_parity_32(data & 0x02d9b333);
31         unsigned parity3 = find_parity_32(data & 0x01c78f0f);
32         unsigned parity4 = find_parity_32(data & 0x003f80ff);
33         unsigned parity5 = find_parity_32(data & 0x00007fff);
34         unsigned parity6 = find_parity_32(data & 0x03b4e996);
35                 
36         return parity6 | (parity5 << 1) | (parity4 << 2) | (parity3 << 3) | (parity2 << 4) | (parity1 << 5);
37 }
38
39 unsigned make_codeword(unsigned data)
40 {
41         return (data << PARITY_BITS) | generate_parity(data);
42 }
43
44 /* can detect all single or double bit errors */
45 int has_error(unsigned code)
46 {
47         unsigned parity = code & ((1 << PARITY_BITS) - 1);
48         return (generate_parity(code >> PARITY_BITS) != parity);
49 }
50
51 int has_double_error(unsigned code)
52 {
53         unsigned parity_diff = generate_parity(code >> PARITY_BITS) ^ code;
54         return (parity_diff & ((1 << PARITY_BITS) - 1)) && !find_parity_32(code);
55 }
56
57 /* Correct any single-bit error -- assumes there are no double-bit errors */
58 unsigned correct_single_bit_error(unsigned code)
59 {
60         unsigned parity_diff = generate_parity(code >> PARITY_BITS) ^ code;
61         unsigned bp = 0, i;
62
63         for (i = 0; i < PARITY_BITS - 1; ++i) {
64                 if (parity_diff & (1 << (PARITY_BITS - 1 - i))) {
65                         bp |= (1 << i);
66                 }
67         }
68         
69         if (bp != 0) {
70                 /* flip the wrong bit */
71                 code ^= (1 << permutation_table[bp]);
72         }
73
74         /* recompute the lower parity */
75         return (code & ~1) | find_parity_32(code & ~1);
76 }
77
78 void check_zero_bit_detection()
79 {
80         unsigned i;
81         printf("Checking zero bit detection.");
82         fflush(stdout);
83
84         for (i = 0; i < NUM_DATA_WORDS; ++i) {
85                 unsigned code = make_codeword(i);
86
87                 if ((i & 0xfffff) == 0) {
88                         printf(".");
89                         fflush(stdout);
90                 }
91                 
92                 if (has_error(code)) {
93                         printf("ERROR: Failed zero-bit test 1 for %x\n", i);
94                 }
95                 if (has_double_error(code)) {
96                         printf("ERROR: Failed zero-bit test 2 for %x\n", i);
97                 }
98         }
99
100         printf("\n");
101 }
102
103 void check_single_bit_detection()
104 {
105         unsigned i, j;
106         printf("Checking single bit detection and correction.");
107         fflush(stdout);
108
109         for (i = 0; i < NUM_DATA_WORDS; ++i) {
110                 unsigned code = make_codeword(i);
111
112                 if ((i & 0xfffff) == 0) {
113                         printf(".");
114                         fflush(stdout);
115                 }
116                 
117                 for (j = 0; j < CODE_BITS; ++j) {
118                         unsigned corrupted_code = code ^ (1 << j);
119                         
120                         if (!has_error(corrupted_code)) {
121                                 printf("ERROR: Failed single-bit test 1 for %x with bit %u flipped\n", i, j);
122                         }
123                         if (has_double_error(corrupted_code)) {
124                                 printf("ERROR: Failed single-bit test 2 for %x with bit %u flipped\n", i, j);
125                         }
126                         if (correct_single_bit_error(corrupted_code) != code) {
127                                 printf("ERROR: Failed single-bit correction test for %x with bit %u flipped\n", i, j);
128                         }
129                 }
130         }
131
132         printf("\n");
133 }
134
135 void check_double_bit_detection()
136 {
137         unsigned i, j, k;
138         printf("Checking double bit detection.");
139         fflush(stdout);
140
141         for (i = 0; i < NUM_DATA_WORDS; ++i) {
142                 unsigned code = make_codeword(i);
143                 
144                 if ((i & 0xfffff) == 0) {
145                         printf(".");
146                         fflush(stdout);
147                 }
148                 
149                 for (j = 0; j < CODE_BITS; ++j) {
150                         for (k = 0; k < CODE_BITS; ++k) {
151                                 unsigned corrupted_code = code ^ (1 << j) ^ (1 << k);
152                                 if (j == k)
153                                         continue;
154                                 
155                                 if (!has_error(corrupted_code)) {
156                                         printf("ERROR: Failed double-bit test 1 for %x with bit %u and %u flipped\n", i, j, k);
157                                 }
158                                 if (!has_double_error(corrupted_code)) {
159                                         printf("ERROR: Failed double-bit test 2 for %x with bit %u and %u flipped\n", i, j, k);
160                                 }
161                         }
162                 }
163         }
164
165         printf("\n");
166 }
167
168 int main()
169 {
170         check_zero_bit_detection();
171         check_single_bit_detection();
172         check_double_bit_detection();
173
174         return 0;
175 }