218 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			218 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /* RCODE.C - Procedures to read parity check and generator matrices. */ | ||
|  | 
 | ||
|  | /* 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 "alloc.h"
 | ||
|  | #include "intio.h"
 | ||
|  | #include "open.h"
 | ||
|  | #include "mod2sparse.h"
 | ||
|  | #include "mod2dense.h"
 | ||
|  | #include "mod2convert.h"
 | ||
|  | #include "rcode.h"
 | ||
|  | 
 | ||
|  | 
 | ||
|  | /* VARIABLES DECLARED IN RCODE.H.  These global variables are set to
 | ||
|  |    representations of the parity check and generator matrices by read_pchk | ||
|  |    and read_gen. */ | ||
|  | 
 | ||
|  | mod2sparse *H;		/* Parity check matrix */ | ||
|  | 
 | ||
|  | int M;			/* Number of rows in parity check matrix */ | ||
|  | int N;			/* Number of columns in parity check matrix */ | ||
|  | 
 | ||
|  | char type;		/* Type of generator matrix representation (s/d/m) */ | ||
|  | int *cols;		/* Ordering of columns in generator matrix */ | ||
|  | 
 | ||
|  | mod2sparse *L, *U;	/* Sparse LU decomposition, if type=='s' */ | ||
|  | int *rows;		/* Ordering of rows in generator matrix (type 's') */ | ||
|  | 
 | ||
|  | mod2dense *G;		/* Dense or mixed representation of generator matrix,
 | ||
|  | 			   if type=='d' or type=='m' */ | ||
|  | 
 | ||
|  | 
 | ||
|  | /* READ PARITY CHECK MATRIX.  Sets the H, M, and N global variables.  If an
 | ||
|  |    error is encountered, a message is displayed on standard error, and the | ||
|  |    program is terminated. */ | ||
|  | 
 | ||
|  | void read_pchk | ||
|  | ( char *pchk_file | ||
|  | ) | ||
|  | { | ||
|  |   FILE *f; | ||
|  | 
 | ||
|  |   f = open_file_std(pchk_file,"rb"); | ||
|  |   if (f==NULL) | ||
|  |   { fprintf(stderr,"Can't open parity check file: %s\n",pchk_file); | ||
|  |     exit(1); | ||
|  |   } | ||
|  | 
 | ||
|  |   if (intio_read(f)!=('P'<<8)+0x80) | ||
|  |   { fprintf(stderr,"File %s doesn't contain a parity check matrix\n",pchk_file); | ||
|  |     exit(1); | ||
|  |   } | ||
|  | 
 | ||
|  |   H = mod2sparse_read(f); | ||
|  | 
 | ||
|  |   if (H==0) | ||
|  |   { fprintf(stderr,"Error reading parity check matrix from %s\n",pchk_file); | ||
|  |     exit(1); | ||
|  |   } | ||
|  | 
 | ||
|  |   M = mod2sparse_rows(H); | ||
|  |   N = mod2sparse_cols(H); | ||
|  | 
 | ||
|  |   fclose(f); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /* READ GENERATOR MATRIX.  The parity check matrix must have already been 
 | ||
|  |    read, unless the last argument is set to 1.  The generator matrix must be  | ||
|  |    compatible with the parity check matrix, if it has been read.  If the  | ||
|  |    second argument is 1, only the column ordering (the last N-M of which are  | ||
|  |    the indexes of the message bits) is read, into the 'cols' global variable.   | ||
|  |    Otherwise, everything is read, into the global variables appropriate | ||
|  |    to the representation.  The 'type' global variable is set to a letter | ||
|  |    indicating which represention is used.  | ||
|  | 
 | ||
|  |    If an error is encountered, a message is displayed on standard error, | ||
|  |    and the program is terminated. */ | ||
|  | 
 | ||
|  | void read_gen | ||
|  | ( char *gen_file,	/* Name of generator matrix file */ | ||
|  |   int cols_only,	/* Read only column ordering? */ | ||
|  |   int no_pchk_file	/* No parity check file used? */ | ||
|  | ) | ||
|  | { | ||
|  |   int M2, N2; | ||
|  |   FILE *f; | ||
|  |   int i; | ||
|  | 
 | ||
|  |   f = open_file_std(gen_file,"rb"); | ||
|  |   if (f==NULL) | ||
|  |   { fprintf(stderr,"Can't open generator matrix file: %s\n",gen_file); | ||
|  |     exit(1); | ||
|  |   } | ||
|  | 
 | ||
|  |   if (intio_read(f)!=('G'<<8)+0x80) | ||
|  |   { fprintf(stderr,"File %s doesn't contain a generator matrix\n",gen_file); | ||
|  |     exit(1); | ||
|  |   } | ||
|  | 
 | ||
|  |   if (fread (&type, 1, 1, f) != 1) goto error; | ||
|  | 
 | ||
|  |   M2 = intio_read(f); | ||
|  |   N2 = intio_read(f); | ||
|  | 
 | ||
|  |   if (feof(f) || ferror(f)) goto error; | ||
|  | 
 | ||
|  |   if (no_pchk_file) | ||
|  |   { M = M2; | ||
|  |     N = N2; | ||
|  |   } | ||
|  |   else  | ||
|  |   { if (M2!=M || N2!=N) | ||
|  |     { fprintf(stderr, | ||
|  |               "Generator matrix and parity-check matrix are incompatible\n"); | ||
|  |       exit(1); | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   cols = chk_alloc (N, sizeof *cols); | ||
|  |   rows = chk_alloc (M, sizeof *rows); | ||
|  | 
 | ||
|  |   for (i = 0; i<N; i++) | ||
|  |   { cols[i] = intio_read(f); | ||
|  |     if (feof(f) || ferror(f)) goto error; | ||
|  |   } | ||
|  | 
 | ||
|  |   if (!cols_only) | ||
|  |   { | ||
|  |     switch (type) | ||
|  |     { | ||
|  |       case 's': | ||
|  |       {  | ||
|  |         for (i = 0; i<M; i++) | ||
|  |         { rows[i] = intio_read(f); | ||
|  |           if (feof(f) || ferror(f)) goto error; | ||
|  |         } | ||
|  | 
 | ||
|  |         if ((L = mod2sparse_read(f)) == 0) goto error; | ||
|  |         if ((U = mod2sparse_read(f)) == 0) goto error; | ||
|  |    | ||
|  |         if (mod2sparse_rows(L)!=M || mod2sparse_cols(L)!=M) goto garbled; | ||
|  |         if (mod2sparse_rows(U)!=M || mod2sparse_cols(U)<M) goto garbled; | ||
|  |         | ||
|  |         break; | ||
|  |       } | ||
|  |    | ||
|  |       case 'd': | ||
|  |       { | ||
|  |         if ((G = mod2dense_read(f)) == 0) goto error; | ||
|  |    | ||
|  |         if (mod2dense_rows(G)!=M || mod2dense_cols(G)!=N-M) goto garbled; | ||
|  |    | ||
|  |         break; | ||
|  |       } | ||
|  |    | ||
|  |       case 'm': | ||
|  |       { | ||
|  |         if ((G = mod2dense_read(f)) == 0) goto error; | ||
|  |    | ||
|  |         if (mod2dense_rows(G)!=M || mod2dense_cols(G)!=M) goto garbled; | ||
|  |    | ||
|  |         break; | ||
|  |       } | ||
|  |    | ||
|  |       default:  | ||
|  |       { fprintf(stderr, | ||
|  |          "Unknown type of generator matrix in file %s\n",gen_file); | ||
|  |         exit(1); | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  |    | ||
|  |   fclose(f); | ||
|  | 
 | ||
|  |   return; | ||
|  | 
 | ||
|  | error: | ||
|  |   fprintf(stderr,"Error reading generator matrix from file %s\n",gen_file); | ||
|  |   exit(1); | ||
|  | 
 | ||
|  | garbled: | ||
|  |   fprintf(stderr,"Garbled generator matrix in file %s\n",gen_file); | ||
|  |   exit(1); | ||
|  | } | ||
|  | 
 | ||
|  | // Fortran interface routines for WSJT-X
 | ||
|  | void init_ldpc_ (char *pfile, char *gfile ) | ||
|  | { | ||
|  |     read_pchk( pfile ); | ||
|  |     read_gen( gfile, 0, 0 ); | ||
|  | } | ||
|  | 
 | ||
|  | void fini_ldpc_ () | ||
|  | { | ||
|  |   mod2dense_free (G); | ||
|  |   mod2sparse_free (U); | ||
|  |   mod2sparse_free (L); | ||
|  |   free (cols); | ||
|  |   free (rows); | ||
|  |   mod2sparse_free (H); | ||
|  | } |