/* This function "order2_dec" written by Marc Fossorier performs order-2 decoding as described in his paper. "Gg_t" is the two-dimensional integer array containing the generator matrix of the code. "R" is the length "N" double-valued received vector containing the received real numbers. "out_D" is the result of order-2 decoding. */ // ------------------------------------------------------------------------ // This program is complementary material for the book: // // R.H. Morelos-Zaragoza, The Art of Error Correcting Coding, Wiley, 2002. // // ISBN 0471 49581 6 // // This and other programs are available at http://the-art-of-ecc.com // // You may use this program for academic and personal purposes only. // If this program is used to perform simulations whose results are // published in a journal or book, please refer to the book above. // // The use of this program in a commercial product requires explicit // written permission from the author. The author is not responsible or // liable for damage or loss that may be caused by the use of this program. // // Copyright (c) 2002. Robert H. Morelos-Zaragoza. All rights reserved. // ------------------------------------------------------------------------ # include "def.h" void order2(Gg_t,R,out_D) int Gg_t[K][N]; double R[N],out_D[N]; { int a,b,c,d; int r,mul_G,e_c1,e_c2,e_c3,e_counter,counter; int count_comp,loss,gain; int c_dh0,c_dh1,c_dh2,c_dh3; double resource_init,resource_available,resource_right,cost_left; double resource_p[N-K],non_resource_p[N-K]; double sum_tail_init,new_sum_tail; double resource_dh0,resource_dh1,resource_dh2,resource_dh3; double resource_dh0_candidate,resource_dh1_candidate,resource_dh2_candidate,resource_dh3_candidate,resource_candidate; int index_p[N-K]; double cost_I[K],cost_row[K]; int step,temp,iter,k,l,index; double cost,tot,Max,min,opti; CHANGE change; double abs_R[N],C[N][2]; int Dd[N],DD[N],GG[K][N],i,j,Gg[K][N]; int permutation_final[N],permutation_I[K],permutation_R[N]; double zero[K],fabs(); void peterson_I_0(),quick_sort_track_0(); void switch_column_I_0(); void switch_vector_0(),switch_matrix_0(); for (i=0;i < K;i++) for (j=0;j < N;j++) Gg[i][j] = Gg_t[i][j]; /*for (i=0;(i Changes the code into an equivalent code */ switch_vector_0(R,permutation_R,N-1); switch_matrix_0(Gg,permutation_R,K-1,N-1); /* Put into systematic code */ /* Row operations => Keeps the code */ peterson_I_0(Gg,zero); /* Obtain the K columns of I */ quick_sort_track_0(zero,permutation_I,0,K-1); /* Switch the rows to obtain the K I_rows in the right order => keeps the code */ for (i=0; i changes the code */ switch_column_I_0(GG,Gg,R,permutation_R,permutation_final); /* Compute 2N costs and K most probable bits */ resource_init = 0.0; k = 0; l = 0; c_dh0 = 0; c_dh1 = 0; c_dh2 = 0; c_dh3 = 0; count_comp = 0; counter = 0; e_counter = 0; for (i=0; i C[i][DD[i]]) { index_p[k] = i; resource_p[k] = C[i][Dd[i]] - C[i][DD[i]]; resource_init = resource_init + resource_p[k]; e_counter++; k++; } else { non_resource_p[l] = C[i][DD[i]] - C[i][Dd[i]]; l++; /* to be used in next loop too */ } } } sum_tail_init = 0.0; resource_dh0 = 0.0; resource_dh1 = 0.0; resource_dh2 = 0.0; resource_dh3 = 0.0; for (i=0,j=l-1;i=0)) { k = 0; resource_right = resource_available- resource_p[k]; cost_left = -cost_I[i]; loss = 0; gain = 0; e_c1 = e_counter; cost_row[i] = cost_I[i]; resource_candidate = - cost_row[i]; for (l=0,j=K; j 0.0)) { non_resource_p[l] = C[j][Dd[j]] - C[j][DD[j]]; l++; /* to be used later */ e_c1--; loss++; } if ((Gg[i][j] == 1) && (C[j][Dd[j]] - C[j][DD[j]] <= 0.0)) { e_c1++; gain++; resource_candidate = resource_candidate - (C[j][Dd[j]] - C[j][DD[j]]); /* new contribution */ } if ((Gg[i][j] == 0) && (C[j][Dd[j]] - C[j][DD[j]] > 0.0)) { resource_candidate = resource_candidate + (C[j][Dd[j]] - C[j][DD[j]]); /* unchanged contribution */ } if ((Gg[i][j] == 0) && (C[j][Dd[j]] - C[j][DD[j]] <= 0.0)) { non_resource_p[l] = C[j][DD[j]] - C[j][Dd[j]]; l++; /* to be used later */ } } if (cost_row[i] > Max) { Max = cost_row[i]; change.n_change = 1; change.position[0] = i; resource_available = resource_init - Max; /* Recompute resource_dhi for new resource_candidate */ resource_dh0 = 0.0; resource_dh1 = 0.0; resource_dh2 = 0.0; resource_dh3 = 0.0; for (a=0,b=l-1;a0;i--) { for (j=i-1;j>=0;j--) { if ((-cost_I[i]-cost_I[j]+resource_dh1) < resource_available) { k = 0; resource_right = resource_available- resource_p[k]; cost_left = -cost_I[i]-cost_I[j]; loss = 0; gain = 0; e_c2 = e_counter; cost = cost_I[i]+cost_I[j]; /* negative value */ resource_candidate = - cost; for (l=0,k=K; k 0.0) { non_resource_p[l] = C[k][Dd[k]] - C[k][DD[k]]; l++; /* to be used later */ e_c2--; loss++; } else { e_c2++; gain++; resource_candidate = resource_candidate - (C[k][Dd[k]] - C[k][DD[k]]); /* new contribution */ } } else { if (C[k][Dd[k]] - C[k][DD[k]] > 0.0) { resource_candidate = resource_candidate + (C[k][Dd[k]] - C[k][DD[k]]); /* unchanged contribution */ } else { non_resource_p[l] = C[k][DD[k]] - C[k][Dd[k]]; l++; /* to be used later */ } } } if (cost > Max) { Max = cost; /* do not reset Max */ change.n_change = 2; change.position[0] = i; change.position[1] = j; resource_available = resource_init - Max; /* Recompute resource_dhi for new resource_candidate */ resource_dh0 = 0.0; resource_dh1 = 0.0; resource_dh2 = 0.0; resource_dh3 = 0.0; for (a=0,b=l-1;a start) /* Unchanged part */ { for(j=0; j 0) /* Copy from R to L dependent columns found in first positions */ { temp[i] = R[i]; for(j=0; j 0) /* Copy I_columns */ { temp[i] = R[i]; for(j=0; j i) /* data not overwritten */ { R[i] = R[permutation[length-i]]; } else { R[i] = temp[permutation[length-i]]; /* data overwritten but stored in temp */ } } } void switch_matrix_0(Gg,permutation,k,n) int Gg[K][N]; int permutation[]; int k,n; { int i,j; double temp[K][N]; for (j=0;j<=n;j++) { for (i=0; i<=k; i++) { temp[i][j] = Gg[i][j]; if (permutation[n-j] > j) /* column not overwritten */ { Gg[i][j] = Gg[i][permutation[n-j]]; } else { Gg[i][j] = temp[i][permutation[n-j]]; /* data overwritten but stored in temp */ } } } } void peterson_I_0(Gg,zero) int Gg[K][N]; double zero[N]; { int i,j,l,m; for (i=0; i left) { ref_val = vals [right]; for(;;) { /* while element smaller than reference value, move left wall upwards */ while (vals [++ascending] < ref_val); /* while element larger than reference value, move right wall downwards */ while (vals [--descending] > ref_val); if (ascending >= descending) break; /* if the walls have not passed each other, exchange values (if not access to function need to save index) */ temp=vals[ascending]; temp2=permutation[ascending]; vals[ascending]=vals[descending]; vals[descending]=temp; permutation[ascending]=permutation[descending]; permutation[descending]=temp2; } temp=vals[ascending]; temp2=permutation[ascending]; vals[ascending]=vals[right]; vals[right]=temp; permutation[ascending]=permutation[right]; permutation[right]=temp2; /* if descending wall has not yet reached left partition, call quick-sort again with this smaller array */ quick_sort_track_0( vals, permutation, left, ascending-1); /* if ascending wall has not yet reached right partition, call quick-sort again with this smaller array */ quick_sort_track_0( vals, permutation, ascending+1, right); } }