174 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			174 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /* ENC.C - Encoding procedures. */ | ||
|  | 
 | ||
|  | /* Copyright (c) 1995-2012 by Radford M. Neal.
 | ||
|  |  * | ||
|  |  * Permission is granted for anyone to copy, use, modify, and distribute | ||
|  |  * these programs and accompanying documents for any purpose, provided | ||
|  |  * this copyright notice is retained and prominently displayed, and note | ||
|  |  * is made of any changes made to these programs.  These programs and | ||
|  |  * documents are distributed without any warranty, express or implied. | ||
|  |  * As the programs were written for research purposes only, they have not | ||
|  |  * been tested to the degree that would be advisable in any important | ||
|  |  * application.  All use of these programs is entirely at the user's own | ||
|  |  * risk. | ||
|  |  */ | ||
|  | 
 | ||
|  | #include <stdio.h>
 | ||
|  | #include <stdlib.h>
 | ||
|  | #include <math.h>
 | ||
|  | 
 | ||
|  | /*#include "rand.h"*/ | ||
|  | #include "alloc.h"
 | ||
|  | #include "mod2sparse.h"
 | ||
|  | #include "mod2dense.h"
 | ||
|  | #include "mod2convert.h"
 | ||
|  | #include "rcode.h"
 | ||
|  | #include "enc.h"
 | ||
|  | 
 | ||
|  | 
 | ||
|  | /* The procedures in this module obtain the generator matrix to use for
 | ||
|  |    encoding from the global variables declared in rcode.h */ | ||
|  | 
 | ||
|  | 
 | ||
|  | /* ENCODE A BLOCK USING A SPARSE REPRESENTATION OF THE GENERATOR MATRIX. */ | ||
|  | 
 | ||
|  | void sparse_encode | ||
|  | ( char *sblk, | ||
|  |   char *cblk | ||
|  | ) | ||
|  | { | ||
|  |   int i, j; | ||
|  | 
 | ||
|  |   mod2entry *e; | ||
|  |   char *x, *y; | ||
|  | 
 | ||
|  |   x = chk_alloc (M, sizeof *x); | ||
|  |   y = chk_alloc (M, sizeof *y); | ||
|  | 
 | ||
|  |   /* Multiply the vector of source bits by the systematic columns of the 
 | ||
|  |      parity check matrix, giving x.  Also copy these bits to the coded block. */ | ||
|  | 
 | ||
|  |   for (i = 0; i<M; i++) x[i] = 0; | ||
|  | 
 | ||
|  |   for (j = M; j<N; j++) | ||
|  |   {  | ||
|  |     cblk[cols[j]] = sblk[j-M]; | ||
|  | 
 | ||
|  |     if (sblk[j-M]==1) | ||
|  |     { for (e = mod2sparse_first_in_col(H,cols[j]); | ||
|  |            !mod2sparse_at_end(e); | ||
|  |            e = mod2sparse_next_in_col(e)) | ||
|  |       { x[mod2sparse_row(e)] ^= 1; | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  |   | ||
|  |   /* Solve Ly=x for y by forward substitution, then U(cblk)=y by backward
 | ||
|  |      substitution. */ | ||
|  | 
 | ||
|  |   if (!mod2sparse_forward_sub(L,rows,x,y) | ||
|  |    || !mod2sparse_backward_sub(U,cols,y,cblk)) | ||
|  |   {  | ||
|  |     abort(); /* Shouldn't occur, even if the parity check matrix has 
 | ||
|  |                 redundant rows */ | ||
|  |   } | ||
|  | 
 | ||
|  |   free(x); | ||
|  |   free(y); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /* ENCODE A BLOCK USING DENSE REPRESENTATION OF GENERATOR MATRIX. */ | ||
|  | 
 | ||
|  | void dense_encode | ||
|  | ( char *sblk, | ||
|  |   char *cblk, | ||
|  |   mod2dense *u, | ||
|  |   mod2dense *v | ||
|  | ) | ||
|  | { | ||
|  |   int j; | ||
|  | 
 | ||
|  |   /* Copy source bits to the systematic part of the coded block. */ | ||
|  | 
 | ||
|  |   for (j = M; j<N; j++)  | ||
|  |   { cblk[cols[j]] = sblk[j-M]; | ||
|  |   } | ||
|  | 
 | ||
|  |   /* Multiply by Inv(A) X B to produce check bits. */ | ||
|  | 
 | ||
|  |   for (j = M; j<N; j++) | ||
|  |   { mod2dense_set(u,j-M,0,sblk[j-M]);  | ||
|  |   } | ||
|  |    | ||
|  |   mod2dense_multiply(G,u,v); | ||
|  | 
 | ||
|  |   /* Copy check bits to the right places in the coded block. */ | ||
|  | 
 | ||
|  |   for (j = 0; j<M; j++) | ||
|  |   { cblk[cols[j]] = mod2dense_get(v,j,0); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /* ENCODE A BLOCK USING MIXED REPRESENTATION OF GENERATOR MATRIX. */ | ||
|  | 
 | ||
|  | void mixed_encode | ||
|  | ( char *sblk, | ||
|  |   char *cblk, | ||
|  |   mod2dense *u, | ||
|  |   mod2dense *v | ||
|  | ) | ||
|  | { | ||
|  |   mod2entry *e; | ||
|  |   int j; | ||
|  | 
 | ||
|  |   /* Multiply the vector of source bits by the message bit columns of the 
 | ||
|  |      parity check matrix.  Also copy these bits to the coded block.  Take | ||
|  |      account of how columns have been reordered. */ | ||
|  | 
 | ||
|  |   mod2dense_clear(u); | ||
|  | 
 | ||
|  |   for (j = M; j<N; j++) | ||
|  |   {  | ||
|  |     cblk[cols[j]] = sblk[j-M]; | ||
|  | 
 | ||
|  |     if (sblk[j-M]==1) | ||
|  |     { for (e = mod2sparse_first_in_col(H,cols[j]); | ||
|  |            !mod2sparse_at_end(e); | ||
|  |            e = mod2sparse_next_in_col(e)) | ||
|  |       { (void) mod2dense_flip(u,mod2sparse_row(e),0); | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   /* Multiply by Inv(A) to produce check bits. */ | ||
|  | 
 | ||
|  |   mod2dense_multiply(G,u,v); | ||
|  | 
 | ||
|  |   /* Copy check bits to the right places in the coded block. */ | ||
|  | 
 | ||
|  |   for (j = 0; j<M; j++) | ||
|  |   { cblk[cols[j]] = mod2dense_get(v,j,0); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | // Wrapper for calling sparse_encode from fortran
 | ||
|  | void ldpc_encode_( | ||
|  | char msg[N-M], | ||
|  | char cdw[N] | ||
|  | ){ | ||
|  |   int i; | ||
|  |   char checks[M]; | ||
|  | 
 | ||
|  |   sparse_encode(msg,cdw); | ||
|  |   mod2sparse_mulvec (H, cdw, checks); | ||
|  |   for (i = 0; i<M; i++) { | ||
|  |     if( checks[i] == 1 ) { | ||
|  |       printf("Failed to encode.\n"); | ||
|  |       abort(); | ||
|  |     } | ||
|  |   }  | ||
|  | } | ||
|  | 
 |