00001 /* File: golay.c 00002 * Title: Encoder/decoder for a binary (23,12,7) Golay code 00003 * Author: Max Luttrell (luttrell@icsl.ucla.edu), 00004 * Date: October 1997 00005 * 00006 * based on work done by: 00007 * Author: Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) 00008 * Date: August 1994 00009 * 00010 * The binary (23,12,7) Golay code is an example of a perfect code, that is, 00011 * the number of syndromes equals the number of correctable error patterns. 00012 * The minimum distance is 7, so all error patterns of Hamming weight up to 00013 * 3 can be corrected. The total number of these error patterns is: 00014 * 00015 * Number of errors Number of patterns 00016 * ---------------- ------------------ 00017 * 0 1 00018 * 1 23 00019 * 2 253 00020 * 3 1771 00021 * ---- 00022 * Total number of error patterns = 2048 = 2^{11} = number of syndromes 00023 * -- 00024 * number of redundant bits -------^ 00025 * 00026 * Because of its relatively low length (23), dimension (12) and number of 00027 * redundant bits (11), the binary (23,12,7) Golay code can be encoded and 00028 * decoded simply by using look-up tables. The program below uses a 16K 00029 * encoding table and an 8K decoding table. 00030 * 00031 * For more information, suggestions, or other ideas on implementing error 00032 * correcting codes, please contact me at (I'm temporarily in Japan, but 00033 * below is my U.S. address): 00034 * 00035 * Robert Morelos-Zaragoza 00036 * 770 S. Post Oak Ln. #200 00037 * Houston, Texas 77056 00038 * 00039 * email: robert@spectra.eng.hawaii.edu 00040 * 00041 * NOTE: This program is free. You may modify it at will. However, please 00042 * include the original file with any redistribution. The author is 00043 * not responsible for any damage caused by the use of this program. 00044 * 00045 * Homework: Add an overall parity-check bit to get the (24,12,8) 00046 * extended Golay code. 00047 * 00048 * == Copyright (c) 1994 Robert Morelos-Zaragoza. All rights reserved. == 00049 */ 00050 00051 #include <stdio.h> 00052 #define X22 0x00400000 /* vector representation of X^{22} */ 00053 #define X11 0x00000800 /* vector representation of X^{11} */ 00054 #define MASK12 0xfffff800 /* auxiliary vector for testing */ 00055 #define GENPOL 0x00000c75 /* generator polinomial, g(x) */ 00056 00057 /* Global variables: 00058 * 00059 * pattern = error pattern, or information, or received vector 00060 * encoding_table[] = encoding table 00061 * decoding_table[] = decoding table 00062 * data = information bits, i(x) 00063 * codeword = code bits = x^{11}i(x) + (x^{11}i(x) mod g(x)) 00064 * numerr = number of errors = Hamming weight of error polynomial e(x) 00065 * position[] = error positions in the vector representation of e(x) 00066 * recd = representation of corrupted received polynomial r(x) = c(x) + e(x) 00067 * decerror = number of decoding errors 00068 * a[] = auxiliary array to generate correctable error patterns 00069 */ 00070 00071 long pattern; 00072 long encoding_table[4096], decoding_table[2048]; 00073 long data, codeword, recd; 00074 long position[23] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 00075 0x00000010, 0x00000020, 0x00000040, 0x00000080, 00076 0x00000100, 0x00000200, 0x00000400, 0x00000800, 00077 0x00001000, 0x00002000, 0x00004000, 0x00008000, 00078 0x00010000, 0x00020000, 0x00040000, 0x00080000, 00079 0x00100000, 0x00200000, 0x00400000 }; 00080 long numerr, errpos[23], decerror = 0; 00081 int a[4]; 00082 extern int debug; 00083 00084 long arr2int(int* a,int r) 00085 /* 00086 * Convert a binary vector of Hamming weight r, and nonzero positions in 00087 * array a[1]...a[r], to a long integer \sum_{i=1}^r 2^{a[i]-1}. 00088 */ 00089 { 00090 int i; 00091 long mul, result = 0, temp; 00092 00093 for (i=1; i<=r; i++) { 00094 mul = 1; 00095 temp = a[i]-1; 00096 while (temp--) 00097 mul = mul << 1; 00098 result += mul; 00099 } 00100 return(result); 00101 } 00102 00103 void nextcomb(int n, int r, int *a) 00104 /* 00105 * Calculate next r-combination of an n-set. 00106 */ 00107 { 00108 int i, j; 00109 00110 a[r]++; 00111 if (a[r] <= n) 00112 return; 00113 j = r - 1; 00114 while (a[j] == n - r + j) 00115 j--; 00116 for (i = r; i >= j; i--) 00117 a[i] = a[j] + i - j + 1; 00118 return; 00119 } 00120 00121 long get_syndrome(long pattern) 00122 /* 00123 * Compute the syndrome corresponding to the given pattern, i.e., the 00124 * remainder after dividing the pattern (when considering it as the vector 00125 * representation of a polynomial) by the generator polynomial, GENPOL. 00126 * In the program this pattern has several meanings: (1) pattern = infomation 00127 * bits, when constructing the encoding table; (2) pattern = error pattern, 00128 * when constructing the decoding table; and (3) pattern = received vector, to 00129 * obtain its syndrome in decoding. 00130 */ 00131 { 00132 long aux = X22; 00133 00134 if (pattern >= X11) 00135 while (pattern & MASK12) { 00136 while (!(aux & pattern)) 00137 aux = aux >> 1; 00138 pattern ^= (aux/X11) * GENPOL; 00139 } 00140 return(pattern); 00141 } 00142 00143 void gen_enc_table(void) 00144 { 00145 /* 00146 * --------------------------------------------------------------------- 00147 * Generate ENCODING TABLE 00148 * 00149 * An entry to the table is an information vector, a 32-bit integer, 00150 * whose 12 least significant positions are the information bits. The 00151 * resulting value is a codeword in the (23,12,7) Golay code: A 32-bit 00152 * integer whose 23 least significant bits are coded bits: Of these, the 00153 * 12 most significant bits are information bits and the 11 least 00154 * significant bits are redundant bits (systematic encoding). 00155 * --------------------------------------------------------------------- 00156 */ 00157 long temp; 00158 for (pattern = 0; pattern < 4096; pattern++) { 00159 temp = pattern << 11; /* multiply information by X^{11} */ 00160 encoding_table[pattern] = temp + get_syndrome(temp);/* add redundancy */ 00161 } 00162 } 00163 00164 void gen_dec_table(void) 00165 { 00166 /* 00167 * --------------------------------------------------------------------- 00168 * Generate DECODING TABLE 00169 * 00170 * An entry to the decoding table is a syndrome and the resulting value 00171 * is the most likely error pattern. First an error pattern is generated. 00172 * Then its syndrome is calculated and used as a pointer to the table 00173 * where the error pattern value is stored. 00174 * --------------------------------------------------------------------- 00175 * 00176 * (1) Error patterns of WEIGHT 1 (SINGLE ERRORS) 00177 */ 00178 long temp; 00179 int i; 00180 00181 decoding_table[0] = 0; 00182 decoding_table[1] = 1; 00183 temp = 1; 00184 for (i=2; i<= 23; i++) { 00185 temp *= 2; 00186 decoding_table[get_syndrome(temp)] = temp; 00187 } 00188 /* 00189 * (2) Error patterns of WEIGHT 2 (DOUBLE ERRORS) 00190 */ 00191 a[1] = 1; a[2] = 2; 00192 temp = arr2int(a,2); 00193 decoding_table[get_syndrome(temp)] = temp; 00194 for (i=1; i<253; i++) { 00195 nextcomb(23,2,a); 00196 temp = arr2int(a,2); 00197 decoding_table[get_syndrome(temp)] = temp; 00198 } 00199 /* 00200 * (3) Error patterns of WEIGHT 3 (TRIPLE ERRORS) 00201 */ 00202 a[1] = 1; a[2] = 2; a[3] = 3; 00203 temp = arr2int(a,3); 00204 decoding_table[get_syndrome(temp)] = temp; 00205 for (i=1; i<1771; i++) { 00206 nextcomb(23,3,a); 00207 temp = arr2int(a,3); 00208 decoding_table[get_syndrome(temp)] = temp; 00209 } 00210 } 00211 00212 00213 long encode_golay(long data) 00214 { 00215 /* 00216 * encodes data and returns the codeword. 00217 * data is assumed to contain 12 bits in the least significant bit positions 00218 * codeword contains the 23 bits in the LSB positions 00219 * 00220 */ 00221 static int initialized=0; 00222 00223 if (!initialized) { 00224 gen_enc_table(); 00225 initialized=1; 00226 } 00227 codeword = encoding_table[data]; 00228 if (debug) printf("encode_golay() - codeword = %#012x\n", codeword); 00229 return codeword; 00230 } 00231 00232 long decode_golay(long codeword) 00233 { 00234 /* 00235 * decodes codeword and returns the dataword contained within. 00236 * 00237 * note: no detection is done here! 00238 * codeword is assumed to contain the 23 bits in the LSB positions 00239 * the returned bits contain the bits in the LSB positions 00240 * 00241 * MSB will be ignored, since this is 23,12 code. 00242 */ 00243 static int initialized=0; 00244 00245 if (!initialized) { 00246 gen_dec_table(); 00247 initialized=1; 00248 } 00249 00250 if (debug) { 00251 printf("decode_golay() - codeword = %#012x\n", codeword); 00252 printf("decode_golay() - syndrome = %#012x\n", get_syndrome(codeword)); 00253 } 00254 00255 /* 00256 * Calculate the syndrome, look up the corresponding error pattern and 00257 * add it to the received vector. 00258 */ 00259 codeword ^= decoding_table[get_syndrome(codeword)]; 00260 00261 if (debug) { 00262 printf("decoded vector = %#012x\n", codeword); 00263 printf("recovered data = %#012x\n", (codeword>>11)); 00264 } 00265 return codeword >> 11; 00266 } 00267 00268 #if(0) 00269 main() 00270 { 00271 long data,encoded,decoded; 00272 data = 0x0b; 00273 printf("data: %x \n",data); 00274 encoded = encode_golay(data); 00275 printf("encoded: %x \n",encoded); 00276 encoded ^= 0xE000; 00277 printf("error encoded: %x \n",encoded); 00278 decoded = decode_golay(encoded); 00279 printf("decoded: %x \n",decoded); 00280 00281 } 00282 #endif 00283