385 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			385 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								/* DECODE.C - Decode blocks of received data. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* 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 <string.h>
							 | 
						||
| 
								 | 
							
								#include <math.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "rand.h"
							 | 
						||
| 
								 | 
							
								#include "alloc.h"
							 | 
						||
| 
								 | 
							
								#include "blockio.h"
							 | 
						||
| 
								 | 
							
								#include "open.h"
							 | 
						||
| 
								 | 
							
								#include "mod2sparse.h"
							 | 
						||
| 
								 | 
							
								#include "mod2dense.h"
							 | 
						||
| 
								 | 
							
								#include "mod2convert.h"
							 | 
						||
| 
								 | 
							
								#include "channel.h"
							 | 
						||
| 
								 | 
							
								#include "rcode.h"
							 | 
						||
| 
								 | 
							
								#include "check.h"
							 | 
						||
| 
								 | 
							
								#include "dec.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void usage(void);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* MAIN PROGRAM. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int main
							 | 
						||
| 
								 | 
							
								( int argc,
							 | 
						||
| 
								 | 
							
								  char **argv
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  char *pchk_file, *rfile, *dfile, *pfile;
							 | 
						||
| 
								 | 
							
								  char **meth;
							 | 
						||
| 
								 | 
							
								  FILE *rf, *df, *pf;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  char *dblk, *pchk;
							 | 
						||
| 
								 | 
							
								  double *lratio;
							 | 
						||
| 
								 | 
							
								  double *bitpr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  double *awn_data;		/* Places to store channel data */
							 | 
						||
| 
								 | 
							
								  int *bsc_data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  unsigned iters;		/* Unsigned because can be huge for enum */
							 | 
						||
| 
								 | 
							
								  double tot_iter;		/* Double because can be huge for enum */
							 | 
						||
| 
								 | 
							
								  double chngd, tot_changed;	/* Double because can be fraction if lratio==1*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  int tot_valid;
							 | 
						||
| 
								 | 
							
								  char junk;
							 | 
						||
| 
								 | 
							
								  int valid;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  int i, j, k;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Look at initial flag arguments. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ldpc_table = 0;
							 | 
						||
| 
								 | 
							
								  blockio_flush = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  while (argc>1)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    if (strcmp(argv[1],"-t")==0)
							 | 
						||
| 
								 | 
							
								    { if (ldpc_table!=0) usage();
							 | 
						||
| 
								 | 
							
								      ldpc_table = 1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else if (strcmp(argv[1],"-T")==0)
							 | 
						||
| 
								 | 
							
								    { if (ldpc_table!=0) usage();
							 | 
						||
| 
								 | 
							
								      ldpc_table = 2;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else if (strcmp(argv[1],"-f")==0)
							 | 
						||
| 
								 | 
							
								    { if (blockio_flush!=0) usage();
							 | 
						||
| 
								 | 
							
								      blockio_flush = 1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else 
							 | 
						||
| 
								 | 
							
								    { break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    argc -= 1;
							 | 
						||
| 
								 | 
							
								    argv += 1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Look at arguments up to the decoding method specification. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!(pchk_file = argv[1])
							 | 
						||
| 
								 | 
							
								   || !(rfile = argv[2])
							 | 
						||
| 
								 | 
							
								   || !(dfile = argv[3]))
							 | 
						||
| 
								 | 
							
								  { usage();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (argv[4]==0 || argv[5]==0) usage();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  k = channel_parse(argv+4,argc-4);
							 | 
						||
| 
								 | 
							
								  if (k<=0)
							 | 
						||
| 
								 | 
							
								  { pfile = argv[4];
							 | 
						||
| 
								 | 
							
								    k = channel_parse(argv+5,argc-5);
							 | 
						||
| 
								 | 
							
								    if (k<=0) usage();
							 | 
						||
| 
								 | 
							
								    meth = argv+5+k;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  { pfile = 0;
							 | 
						||
| 
								 | 
							
								    meth = argv+4+k;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Look at the specification of the decoding method, which starts at meth and
							 | 
						||
| 
								 | 
							
								     continues to the end of the command line (marked by a zero pointer). */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!meth[0]) usage();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (strcmp(meth[0],"prprp")==0)
							 | 
						||
| 
								 | 
							
								  { dec_method = Prprp;
							 | 
						||
| 
								 | 
							
								    if (!meth[1] || sscanf(meth[1],"%d%c",&max_iter,&junk)!=1 || meth[2]) 
							 | 
						||
| 
								 | 
							
								    { usage();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else if (strcmp(meth[0],"enum-block")==0)
							 | 
						||
| 
								 | 
							
								  { dec_method = Enum_block;
							 | 
						||
| 
								 | 
							
								    if (!(gen_file = meth[1]) || meth[2]) usage();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else if (strcmp(meth[0],"enum-bit")==0)
							 | 
						||
| 
								 | 
							
								  { dec_method = Enum_bit;
							 | 
						||
| 
								 | 
							
								    if (!(gen_file = meth[1]) || meth[2]) usage();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else 
							 | 
						||
| 
								 | 
							
								  { usage();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Check that we aren't overusing standard input or output. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ((strcmp(pchk_file,"-")==0) 
							 | 
						||
| 
								 | 
							
								    + (strcmp(rfile,"-")==0) > 1)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"Can't read more than one stream from standard input\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if ((ldpc_table>0) 
							 | 
						||
| 
								 | 
							
								    + (strcmp(dfile,"-")==0) 
							 | 
						||
| 
								 | 
							
								    + (pfile!=0 && strcmp(pfile,"-")==0) > 1)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"Can't send more than one stream to standard output\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Read parity check file. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  read_pchk(pchk_file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (N<=M)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,
							 | 
						||
| 
								 | 
							
								     "Number of bits (%d) should be greater than number of checks (%d)\n",N,M);
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Open file of received data. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  rf = open_file_std(rfile,"r");
							 | 
						||
| 
								 | 
							
								  if (rf==NULL)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"Can't open file of received data: %s\n",rfile);
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Create file for decoded data. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  df = open_file_std(dfile,"w");
							 | 
						||
| 
								 | 
							
								  if (df==NULL)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"Can't create file for decoded data: %s\n",dfile);
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Create file for bit probabilities, if specified. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (pfile)
							 | 
						||
| 
								 | 
							
								  { pf = open_file_std(pfile,"w");
							 | 
						||
| 
								 | 
							
								    if (pf==NULL)
							 | 
						||
| 
								 | 
							
								    { fprintf(stderr,"Can't create file for bit probabilities: %s\n",pfile);
							 | 
						||
| 
								 | 
							
								      exit(1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Allocate space for data from channel. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  switch (channel)
							 | 
						||
| 
								 | 
							
								  { case BSC:
							 | 
						||
| 
								 | 
							
								    { bsc_data = chk_alloc (N, sizeof *bsc_data);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    case AWGN: case AWLN:
							 | 
						||
| 
								 | 
							
								    { awn_data = chk_alloc (N, sizeof *awn_data);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								    { abort();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Allocate other space. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  dblk   = chk_alloc (N, sizeof *dblk);
							 | 
						||
| 
								 | 
							
								  lratio = chk_alloc (N, sizeof *lratio);
							 | 
						||
| 
								 | 
							
								  pchk   = chk_alloc (M, sizeof *pchk);
							 | 
						||
| 
								 | 
							
								  bitpr  = chk_alloc (N, sizeof *bitpr);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Print header for summary table. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (ldpc_table==1)
							 | 
						||
| 
								 | 
							
								  { printf("  block iterations valid  changed\n");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Do the setup for the decoding method. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  switch (dec_method)
							 | 
						||
| 
								 | 
							
								  { case Prprp: 
							 | 
						||
| 
								 | 
							
								    { prprp_decode_setup();
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    case Enum_block: case Enum_bit:
							 | 
						||
| 
								 | 
							
								    { enum_decode_setup();
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    default: abort();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Read received blocks, decode, and write decoded blocks. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  tot_iter = 0;
							 | 
						||
| 
								 | 
							
								  tot_valid = 0;
							 | 
						||
| 
								 | 
							
								  tot_changed = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (block_no = 0; ; block_no++)
							 | 
						||
| 
								 | 
							
								  { 
							 | 
						||
| 
								 | 
							
								    /* Read block from received file, exit if end-of-file encountered. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (i = 0; i<N; i++)
							 | 
						||
| 
								 | 
							
								    { int c;
							 | 
						||
| 
								 | 
							
								      switch (channel)
							 | 
						||
| 
								 | 
							
								      { case BSC:  
							 | 
						||
| 
								 | 
							
								        { c = fscanf(rf,"%1d",&bsc_data[i]); 
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        case AWGN: case AWLN:
							 | 
						||
| 
								 | 
							
								        { c = fscanf(rf,"%lf",&awn_data[i]); 
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        default: abort();
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if (c==EOF) 
							 | 
						||
| 
								 | 
							
								      { if (i>0)
							 | 
						||
| 
								 | 
							
								        { fprintf(stderr,
							 | 
						||
| 
								 | 
							
								          "Warning: Short block (%d long) at end of received file ignored\n",i);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        goto done;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if (c<1 || channel==BSC && bsc_data[i]!=0 && bsc_data[i]!=1)
							 | 
						||
| 
								 | 
							
								      { fprintf(stderr,"File of received data is garbled\n");
							 | 
						||
| 
								 | 
							
								        exit(1);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Find likelihood ratio for each bit. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    switch (channel)
							 | 
						||
| 
								 | 
							
								    { case BSC:
							 | 
						||
| 
								 | 
							
								      { for (i = 0; i<N; i++)
							 | 
						||
| 
								 | 
							
								        { lratio[i] = bsc_data[i]==1 ? (1-error_prob) / error_prob
							 | 
						||
| 
								 | 
							
								                                     : error_prob / (1-error_prob);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      case AWGN:
							 | 
						||
| 
								 | 
							
								      { for (i = 0; i<N; i++)
							 | 
						||
| 
								 | 
							
								        { lratio[i] = exp(2*awn_data[i]/(std_dev*std_dev));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      case AWLN:
							 | 
						||
| 
								 | 
							
								      { for (i = 0; i<N; i++)
							 | 
						||
| 
								 | 
							
								        { double e, d1, d0;
							 | 
						||
| 
								 | 
							
								          e = exp(-(awn_data[i]-1)/lwidth);
							 | 
						||
| 
								 | 
							
								          d1 = 1 / ((1+e)*(1+1/e));
							 | 
						||
| 
								 | 
							
								          e = exp(-(awn_data[i]+1)/lwidth);
							 | 
						||
| 
								 | 
							
								          d0 = 1 / ((1+e)*(1+1/e));
							 | 
						||
| 
								 | 
							
								          lratio[i] = d1/d0;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      default: abort();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Try to decode using the specified method. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    switch (dec_method)
							 | 
						||
| 
								 | 
							
								    { case Prprp:
							 | 
						||
| 
								 | 
							
								      { iters = prprp_decode (H, lratio, dblk, pchk, bitpr);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      case Enum_block: case Enum_bit:
							 | 
						||
| 
								 | 
							
								      { iters = enum_decode (lratio, dblk, bitpr, dec_method==Enum_block);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      default: abort();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* See if it worked, and how many bits were changed. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    valid = check(H,dblk,pchk)==0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    chngd = changed(lratio,dblk,N);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    tot_iter += iters;
							 | 
						||
| 
								 | 
							
								    tot_valid += valid;
							 | 
						||
| 
								 | 
							
								    tot_changed += chngd;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Print summary table entry. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (ldpc_table==1)
							 | 
						||
| 
								 | 
							
								    { printf ("%7d %10f    %d  %8.1f\n",
							 | 
						||
| 
								 | 
							
								        block_no, (double)iters, valid, (double)chngd);
							 | 
						||
| 
								 | 
							
								        /* iters is printed as a double to avoid problems if it's >= 2^31 */
							 | 
						||
| 
								 | 
							
								      fflush(stdout);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Write decoded block. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    blockio_write(df,dblk,N);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Write bit probabilities, if asked to. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (pfile)
							 | 
						||
| 
								 | 
							
								    { for (j = 0; j<N; j++)
							 | 
						||
| 
								 | 
							
								      { fprintf(pf," %.5f",bitpr[j]);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      fprintf(pf,"\n");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Check for errors when writing. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (ferror(df) || pfile && ferror(pf))
							 | 
						||
| 
								 | 
							
								    { break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Finish up. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								done: 
							 | 
						||
| 
								 | 
							
								  fprintf(stderr,
							 | 
						||
| 
								 | 
							
								  "Decoded %d blocks, %d valid.  Average %.1f iterations, %.0f%% bit changes\n",
							 | 
						||
| 
								 | 
							
								   block_no, tot_valid, (double)tot_iter/block_no, 
							 | 
						||
| 
								 | 
							
								   100.0*(double)tot_changed/(N*block_no));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (ferror(df) || fclose(df)!=0)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"Error writing decoded blocks to %s\n",dfile);
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (pfile)
							 | 
						||
| 
								 | 
							
								  { if (ferror(pf) || fclose(pf)!=0)
							 | 
						||
| 
								 | 
							
								    { fprintf(stderr,"Error writing bit probabilities to %s\n",dfile);
							 | 
						||
| 
								 | 
							
								      exit(1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  exit(0);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* PRINT USAGE MESSAGE AND EXIT. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void usage(void)
							 | 
						||
| 
								 | 
							
								{ fprintf(stderr,"Usage:\n");
							 | 
						||
| 
								 | 
							
								  fprintf(stderr,
							 | 
						||
| 
								 | 
							
								"  decode [ -f ] [ -t | -T ] pchk-file received-file decoded-file [ bp-file ] channel method\n");
							 | 
						||
| 
								 | 
							
								  channel_usage();
							 | 
						||
| 
								 | 
							
								  fprintf(stderr,
							 | 
						||
| 
								 | 
							
								"Method:  enum-block gen-file | enum-bit gen-file | prprp [-]max-iterations\n");
							 | 
						||
| 
								 | 
							
								  exit(1);
							 | 
						||
| 
								 | 
							
								}
							 |