📄 ldpc_awgn.c
字号:
/*********************************************************************************** FILENAME: ldpc_awgn.c version 1.0 (C) jftian, 2003 An LDPC code simulator based on spa algorithm for AWGN chanel********************************************************************************* ChangeLog: 1st,Jan., 2004 : Build********************************************************************************** How to run********************************************************************************* ldpc_awgn filename_of_configuration_file(.cfg) snr Example: ldpc_awgn H_15_7 1.0/**********************************************************************************/// Inlucde files and macros/**********************************************************************************/#include <stdio.h>#include <stdlib.h>#include <math.h>#include <string.h>
#include <time.h>#define OFF 0#define ON 1#define BIT 0#define BLOCK 1#define MAX_STR_LEN 100#define ran01 (rand()/((double)RAND_MAX+0.1))//#define TEST1 // simulate for spa()//#define TEST_tian // simulate with no input
#define TEST2 // simulate with encoding
//#define debug/**********************************************************************************/// Global variables/**********************************************************************************///-------------------------------------for spa()int *tmp_bit; // tentetative decision bitdouble **alpha; // check to variable messagedouble **beta; // variable to check messageint n; // code lengthint m; // number of constraintsint rmax; // maximum number of row weightint cmax; // maximum number of column weightint *row_weight; // row weightsint *col_weight; // column weightsint **row_list; // row list of parity check matrixint **col_list_r; // column list 1int **col_list_c; // column list 1double *LLR; // array for received LLR valuesdouble *forward; // forward array for check node operationdouble *backward; // backward array for check node operationint max_itr; // maximum number of iterations in BP//-------------------------------------for simulation_loop()double code_rate; // code rateint total_iterations; // total number of iterationsint seed; // seed for random number generatorchar *file_name; // filename of configuration file(no suffix)
char *char_snr;
char char_snr_add[MAX_STR_LEN];
char config_file[MAX_STR_LEN], log_file[MAX_STR_LEN];
char *suffix1;
char *suffix2;int total_blocks; // total number of tested blocksint total_bits; // total number of tested bitsint error_blocks; // number of error blocksint error_bits; // number of error bitsint total_miscorrection; // number of mis corrected blocksint display_result; // display switchint stop_condition; // stop conditionint stop_errors; // number of errors for stop conditionint error_logging; // error logging switchdouble target_error_prob; // target error probabilityint *punc_ptn; // puncture patternint puncture; // puncture switchint met; // multi-edge type switchint *vnode_type; // variable node typeint num_vnode_type; // number of variable node typeFILE *error_log; // error log fileint *vnode_errors; // number of variable node errorsint minsum; // min-sum algorithm switchdouble norm_factor; // normalization factorint parity_check; // parity check switchint encoding;//-------------------------------------for encodingint e_n; // code lengthint e_m; // number of parity symbolsint e_rmax; // maximum number of row weightint e_cmax; // maximum number of column weightint *e_row_weight; // row weightsint *e_col_weight; // column weightsint **e_row_list; // parity check matrix//-------------------------------------channel dependent parametersint *cword; // sent codeworddouble *rword; // received word at receiverdouble channel_var; // channel variancedouble snr; // signal to noise ratio (Eb/N0)/**********************************************************************************/// encoding functions (used only for TEST2)/**********************************************************************************/void usage(void)
{ fprintf (stderr,
"Usage: ldpc_awgn config-file[*.cfg] SNR\n");
exit(1);
}
void read_encfile(FILE *fp){ int i,j; int v; fscanf(fp,"%d %d\n",&e_n,&e_m); fscanf(fp,"%d %d\n",&e_rmax,&e_cmax); e_row_weight = malloc(sizeof(int)*e_m); for (i = 0; i <= e_m-1; i++) fscanf(fp,"%d",&e_row_weight[i]); e_col_weight = malloc(sizeof(int)*e_n); for (i = 0; i <= e_n-1; i++) fscanf(fp,"%d",&e_col_weight[i]); e_row_list = malloc(sizeof(int*)*e_m); for (i=0;i<=e_m-1;i++) e_row_list[i] = malloc(sizeof(int)*e_rmax); for (j = 0; j <= e_m-1; j++) { for (i = 0; i <= e_row_weight[j]-1; i++) { fscanf(fp,"%d",&v); v--; e_row_list[j][i] = v; } }}void print_encfile(){ int i,j; printf("encoder file ----------------------\n"); printf("%d %d\n",e_n,e_m); printf("%d %d\n",e_rmax,e_cmax); for (i=0;i<=e_m-1;i++) { for (j=0;j<=e_row_weight[i]-1;j++) printf("%d ",e_row_list[i][j]+1); printf("\n"); }}void gen_info_seq(int *seq){ int i; for (i = 0; i <= e_m-1; i++) seq[i] = 0; for (i = e_m; i <= n-1; i++) { if (ran01> 0.5) seq[i] = 1; else seq[i] = 0; } return;}void print_seq(int *seq){ int i; for (i = 0; i <= n-1; i++) printf("%d ",seq[i]); printf("\n");}void encode_word(int* word)
{
int i,j;
int parity;
for (j = 0; j < e_m; j++) {
parity = 0;
for (i = 0; i < e_row_weight[j]; i++)
parity += word[e_m+e_row_list[j][i]];
word[j] = parity % 2;
}
}int parity_check_func(int *seq)
{
int i,j;
int flag,parity;
flag = 0;
for (i=0; i <= m-1; i++) {
parity = 0;
for (j=0; j <= row_weight[i]-1; j++)
parity = (parity + seq[row_list[i][j]]) % 2;
if (parity == 1) {flag = -1;break;}
}
return flag;
}void print_spmat(){ int i,j; printf("----------------------\n"); printf("%d %d\n",n,m); printf("%d %d\n",rmax,cmax); for (i=0;i<=m-1;i++) { for (j=0;j<=row_weight[i]-1;j++) printf("%d ",row_list[i][j]); printf("\n"); } for (i=0;i<=n-1;i++) printf("%d",punc_ptn[i]); printf("\n");}/**********************************************************************************/// functions for quantized BP algorithm/**********************************************************************************/double nrnd(double var) // gaussian random number generator{ static int sw = 0; static double r1, r2, s; if (sw == 0) { sw = 1; do { r1 = 2 * ran01 - 1; r2 = 2 * ran01 - 1; s = r1 * r1 + r2 * r2; } while (s > 1 || s == 0); s = sqrt(-2 * log(s) / s); return r1 * s * sqrt(var); } else { sw = 0; return r2 * s * sqrt(var); }}double tanh(double x){ return (exp(2*x)-1)/(exp(2*x)+1);}double atanh(double x){ return log((1+x)/(1-x))/2;}double fi_ldpc(double x){ return -log(tanh(x/2.0));}double R(double a, double b) // function for check node operation{ return 2.0 * atanh(tanh(a/2.0)*tanh(b/2.0));}double sign(double a){ if (a == 0.0) return 0.0; else if (a > 0.0) return 1.0; else return -1.0;}int float_spa(double *llr) { int i,j,k; double sum; int loop; double posterior; double a,b; int flag,parity,ret; double beta_tmp; int rwm1; double coef; // initialization of alpha for (i=0; i <= m-1; i++) { for (j=0; j <= row_weight[i]-1; j++) { alpha[i][j] = 0; } } // for (i = 0; i <= n-1; i++) qLLR[i] = quantize(llr[i]); ret = -1; for (loop = 0; loop <= max_itr-1; loop++) { // start of iteration // variable node operation for (i = 0; i <= n-1; i++) { sum = 0; for (k = 0; k <= col_weight[i]-1; k++) sum += alpha[col_list_r[i][k]][col_list_c[i][k]]; for (j = 0; j <= col_weight[i]-1; j++) { if (punc_ptn[i] == 0) beta_tmp = llr[i] + sum-alpha[col_list_r[i][j]][col_list_c[i][j]]; else beta_tmp = sum-alpha[col_list_r[i][j]][col_list_c[i][j]];// if ((minsum == ON) && (norm_factor > 0.0)) // beta_tmp = quantize((double)beta_tmp * DELTA/norm_factor);// if (beta_tmp < LB2) beta_tmp = LB2;// if (beta_tmp > UB2) beta_tmp = UB2; beta[col_list_r[i][j]][col_list_c[i][j]] = beta_tmp; } if (punc_ptn[i] == 0) posterior = llr[i] + sum; else posterior = sum;#ifdef TEST1 printf("%f ",posterior);#endif if (posterior > 0) tmp_bit[i] = 0; if (posterior < 0) tmp_bit[i] = 1; if (posterior == 0) { if (ran01 < 0.5) tmp_bit[i] = 0; else tmp_bit[i] = 1; } } #ifdef TEST1 printf("\n");#endif // check node operation (use spa ) for (i = 0; i <= m-1; i++) { rwm1 = row_weight[i]-1; // foward computation for (k = 0; k <= rwm1; k++) { if (k == 0) { a = fi_ldpc (fabs(beta[i][k]));
coef = sign(beta[i][k]); } else { b = fi_ldpc(fabs(beta[i][k])); a = a+b; //R_tbl[a+UB][b+UB]; coef = coef*sign(beta[i][k]); }
#ifdef debug
printf("%f %f %f\n",a,b,coef);
#endif forward[k] = a; } // backward computation for (k = rwm1; k >= 0 ; k--) { if (k == rwm1) { a = fi_ldpc(fabs(beta[i][k])); } else { b = fi_ldpc(fabs(beta[i][k])); a = a+b; //R_tbl[a+UB][b+UB]; } backward[k] = a; } // update of alpha for (k = 0; k <= rwm1; k++) { if (k == 0) alpha[i][k] = fi_ldpc(backward[1])*coef/sign(beta[i][k]); else if (k == rwm1) alpha[i][k] = fi_ldpc(forward[rwm1-1])*coef/sign(beta[i][k]); else alpha[i][k] = fi_ldpc(forward[k-1]+backward[k+1])*coef/sign(beta[i][k]);
#ifdef debug
printf("%f\n",alpha[i][k]);
#endif //R_tbl[forward[k-1]+UB][backward[k+1]+UB]; } } /* parity check */ if (parity_check == ON) { flag = 0; for (i=0; i <= m-1; i++) { parity = 0; for (j=0; j <= row_weight[i]-1; j++) parity = (parity + tmp_bit[row_list[i][j]]); if (parity % 2 == 1) flag = 1; } if (flag == 0) { ret = 0; break; } } } total_iterations += loop; return ret;}double min_d(double a, double b){ if (a > b) return b; else return a;}double minsumR(double a, double b) // function for check node operation of min-sum algotithm{ return sign(a) * sign(b) * min_d(fabs(a),fabs(b));}void init_dec(FILE *fp){/**********************************************************************************/// initialization of spa decoder/**********************************************************************************/ int i,j; int v; int *counter; int tmp;// read parity check matrix fscanf(fp,"%d %d\n",&n,&m); // n:code length, m:number of parity checks fscanf(fp,"%d %d\n",&rmax,&cmax); // rmax:maximum number of row weight // cmax:maximum number of column weight row_weight = malloc(sizeof(int)*m); // array for row weight profile for (i = 0; i <= m-1; i++) fscanf(fp,"%d",&row_weight[i]); col_weight = malloc(sizeof(int)*n); // array for column weight profile for (i = 0; i <= n-1; i++) fscanf(fp,"%d",&col_weight[i]); counter = malloc(sizeof(int)*n); for (i=0; i <= n-1; i++) counter[i] = 0; row_list = malloc(sizeof(int*)*m); // parity check matrix in row form for (i=0;i<=m-1;i++) row_list[i] = malloc(sizeof(int)*rmax); col_list_r = malloc(sizeof(int*)*n); for (i=0;i<=n-1;i++) col_list_r[i] = malloc(sizeof(int)*cmax); col_list_c = malloc(sizeof(int*)*n); for (i=0;i<=n-1;i++) col_list_c[i] = malloc(sizeof(int)*cmax);// set up for parity check matrix for (j = 0; j <= m-1; j++) { for (i = 0; i <= row_weight[j]-1; i++) { fscanf(fp,"%d",&v); v--; row_list[j][i] = v; col_list_r[v][counter[v]] = j; col_list_c[v][counter[v]] = i; counter[v]++; } } punc_ptn = malloc(sizeof(int) * n); // puncture pattern (0:no puncture, 1:puncture) if (puncture == ON) for (i = 0; i<=n-1; i++) fscanf(fp,"%d",&punc_ptn[i]); else for (i = 0; i<=n-1; i++) punc_ptn[i] = 0; if (met == ON) { vnode_type = malloc(sizeof(int)*n); fscanf(fp,"%d",&tmp); for (i = 0; i<=m-1; i++) fscanf(fp,"%d",&tmp); fscanf(fp,"%d",&num_vnode_type); for (i = 0; i<=n-1; i++) fscanf(fp,"%d",&vnode_type[i]); vnode_errors = malloc(sizeof(int)*num_vnode_type); for (i = 0; i <= num_vnode_type-1; i++) vnode_errors[i] = 0; } // set up for BP related global variables alpha = malloc(sizeof(double*)*m); // check to variable message for (i=0;i<=m-1;i++) alpha[i] = malloc(sizeof(double)*rmax); beta = malloc(sizeof(double*)*m); // variable to check message for (i=0;i<=m-1;i++) beta[i] = malloc(sizeof(double)*rmax); tmp_bit = malloc(sizeof(int)*n); // tentative decoding result // set up of table for check node operation
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -