commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] gr-error-correcting-codes/src/lib/libecc Makefi...


From: Michael Dickens
Subject: [Commit-gnuradio] gr-error-correcting-codes/src/lib/libecc Makefi...
Date: Mon, 03 Jul 2006 02:14:12 +0000

CVSROOT:        /sources/gnuradio
Module name:    gr-error-correcting-codes
Changes by:     Michael Dickens <michaelld>     06/07/03 02:14:12

Added files:
        src/lib/libecc : Makefile.am code_metrics.cc code_metrics.h 
                         encoder.h encoder_convolutional.cc 
                         encoder_convolutional.h 
        src/lib/libecc/mld: Makefile.am mld_timer.cc mld_timer.h n2bs.cc 
                            n2bs.h 

Log message:
        Initial checkin.  Work in progress.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/Makefile.am?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/code_metrics.cc?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/code_metrics.h?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder.h?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/mld/Makefile.am?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/mld/mld_timer.cc?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/mld/mld_timer.h?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.cc?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.h?cvsroot=gnuradio&rev=1.1

Patches:
Index: Makefile.am
===================================================================
RCS file: Makefile.am
diff -N Makefile.am
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Makefile.am 3 Jul 2006 02:14:12 -0000       1.1
@@ -0,0 +1,44 @@
+#
+# Copyright 2006 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+include $(top_srcdir)/Makefile.common
+
+SUBDIRS = mld .
+
+INCLUDES = $(STD_DEFINES_AND_INCLUDES) -I..
+
+noinst_LTLIBRARIES = libecc.la
+
+libecc_la_SOURCES =    \
+       encoder_convolutional.cc code_metrics.cc
+
+noinst_HEADERS =       \
+       encoder.h encoder_convolutional.h code_metrics.h
+
+# link the library against the c++ standard library
+libecc_la_LIBADD =             \
+       mld/libmld.la           \
+       $(PYTHON_LDFLAGS)       \
+       -lstdc++
+
+MOSTLYCLEANFILES = *.loT *~
+
+CONFIG_CLEAN_FILES = *.in

Index: code_metrics.cc
===================================================================
RCS file: code_metrics.cc
diff -N code_metrics.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ code_metrics.cc     3 Jul 2006 02:14:12 -0000       1.1
@@ -0,0 +1,438 @@
+/* -*- c++ -*- */
+/*
+ * Copyright @ 2006 Michael Dickens
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this library; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <code_metrics.h>
+#include <iostream>
+#include <math.h>
+
+code_metric_ff::code_metric_ff (pdf_fcn_t pdf_fcn_0_bit,
+                                 pdf_fcn_t pdf_fcn_1_bit,
+                                 size_t n_samples,
+                                 pdf_fcn_io_t min_sample,
+                                 pdf_fcn_io_t max_sample)
+{
+  if (n_samples < 2) {
+    fprintf (stderr, "code_metric_f32:: n_samples "
+            "must be at least 2.\n");
+    assert (0);
+  }
+  if (min_sample >= max_sample) {
+    fprintf (stderr, "code_metric_f32:: min_sample must be "
+            "less than max_sample.\n");
+    assert (0);
+  }
+  if (! pdf_fcn_0_bit) {
+    fprintf (stderr, "code_metric_f32:: pdf_fcn_0_bit must be "
+            "a non-null pointer to function.\n");
+    assert (0);
+  }
+  if (! pdf_fcn_1_bit) {
+    fprintf (stderr, "code_metric_f32:: pdf_fcn_0_bit must be "
+            "a non-null pointer to function.\n");
+    assert (0);
+  }
+
+  d_n_samples = n_samples;
+  d_max_sample = max_sample;
+  d_min_sample = min_sample;
+  d_delta = (max_sample - min_sample) / (n_samples - 1);
+  d_pdf_fcn_0_bit = pdf_fcn_0_bit;
+  d_pdf_fcn_1_bit = pdf_fcn_1_bit;
+  d_metric_table_0_bit.assign (n_samples, 0);
+  d_metric_table_1_bit.assign (n_samples, 0);
+
+  pdf_fcn_io_t l_val = min_sample;
+  for (size_t m = 0; m < n_samples; m++) {
+    d_metric_table_0_bit[m] = logf ((*pdf_fcn_0_bit)(l_val));
+    d_metric_table_1_bit[m] = logf ((*pdf_fcn_1_bit)(l_val));
+    l_val += d_delta;
+  }
+}
+
+void code_metric_ff::lookup
+(pdf_fcn_io_t sym,
+ void* bit_0,
+ void* bit_1)
+{
+  metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
+  metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
+
+  if (sym <= d_min_sample) {
+    *l_bit_0 = d_metric_table_0_bit[0];
+    *l_bit_1 = d_metric_table_1_bit[0];
+    return;
+  }
+  if (sym >= d_max_sample) {
+    *l_bit_0 = d_metric_table_0_bit.back ();
+    *l_bit_1 = d_metric_table_1_bit.back ();
+    return;
+  }
+
+  size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta);
+  *l_bit_0 = d_metric_table_0_bit[l_ndx];
+  *l_bit_1 = d_metric_table_1_bit[l_ndx];
+}
+
+void code_metric_ff::convert
+(size_t n_syms,
+ pdf_fcn_io_t* sym,
+ void* bit_0,
+ void* bit_1)
+{
+  metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
+  metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
+
+  for (size_t m = n_syms; m > 0; m--)
+    lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
+}
+
+code_metric_fl::code_metric_fl (pdf_fcn_t pdf_fcn_0_bit,
+                                 pdf_fcn_t pdf_fcn_1_bit,
+                                 size_t n_samples,
+                                 pdf_fcn_io_t min_sample,
+                                 pdf_fcn_io_t max_sample,
+                                 int sample_precision)
+{
+  if (n_samples < 2) {
+    fprintf (stderr, "code_metric_fl:: n_samples "
+            "must be at least 2.\n");
+    assert (0);
+  }
+  if (min_sample >= max_sample) {
+    fprintf (stderr, "code_metric_fl:: min_sample must be "
+            "less than max_sample.\n");
+    assert (0);
+  }
+  if (! pdf_fcn_0_bit) {
+    fprintf (stderr, "code_metric_fl:: pdf_fcn_0_bit must be "
+            "a non-null pointer to function.\n");
+    assert (0);
+  }
+  if (! pdf_fcn_1_bit) {
+    fprintf (stderr, "code_metric_fl:: pdf_fcn_0_bit must be "
+            "a non-null pointer to function.\n");
+    assert (0);
+  }
+  if (sample_precision < 16 || sample_precision > 32) {
+    fprintf (stderr, "code_metric_fl:: sample_precision must be "
+            "between 16 and 32 for this class.\n");
+    assert (0);
+  }
+
+  d_sample_precision = sample_precision;
+  d_n_samples = n_samples;
+  d_max_sample = max_sample;
+  d_min_sample = min_sample;
+  d_delta = (max_sample - min_sample) / (n_samples - 1);
+  d_pdf_fcn_0_bit = pdf_fcn_0_bit;
+  d_pdf_fcn_1_bit = pdf_fcn_1_bit;
+  d_metric_table_0_bit.assign (n_samples, 0);
+  d_metric_table_1_bit.assign (n_samples, 0);
+
+// get the scale factor for converting from float to sample_precision
+// maps:
+//    logf (pdf_fcn_0_bit->eval (d_min_sample))  ->  l_min_map
+//    logf (pdf_fcn_0_bit->eval (d_max_sample))  ->  l_max_map
+
+  metric_t l_min_map = - (1 << (sample_precision - 1));
+
+  pdf_fcn_io_t l_min_log_val_0 = logf ((*pdf_fcn_0_bit)(d_min_sample));
+  pdf_fcn_io_t l_max_log_val_0 = logf ((*pdf_fcn_0_bit)(d_max_sample));
+  pdf_fcn_io_t l_slope_0 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
+                           (l_max_log_val_0 - l_min_log_val_0));
+  pdf_fcn_io_t l_min_log_val_1 = logf ((*pdf_fcn_1_bit)(d_min_sample));
+  pdf_fcn_io_t l_max_log_val_1 = logf ((*pdf_fcn_1_bit)(d_max_sample));
+  pdf_fcn_io_t l_slope_1 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
+                           (l_max_log_val_1 - l_min_log_val_1));
+
+  pdf_fcn_io_t l_val = d_min_sample;
+  for (size_t m = 0; m < d_n_samples; m++) {
+    d_metric_table_0_bit[m] =
+      (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
+                        (l_slope_0 * (logf ((*pdf_fcn_0_bit)(l_val)) -
+                                      l_min_log_val_0)));
+    d_metric_table_1_bit[m] =
+      (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
+                        (l_slope_1 * (logf ((*pdf_fcn_1_bit)(l_val)) -
+                                      l_min_log_val_1)));
+    l_val += d_delta;
+  }
+}
+
+void code_metric_fl::lookup
+(pdf_fcn_io_t sym,
+ void* bit_0,
+ void* bit_1)
+{
+  metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
+  metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
+
+  if (sym <= d_min_sample) {
+    *l_bit_0 = d_metric_table_0_bit[0];
+    *l_bit_1 = d_metric_table_1_bit[0];
+    return;
+  }
+  if (sym >= d_max_sample) {
+    *l_bit_0 = d_metric_table_0_bit.back ();
+    *l_bit_1 = d_metric_table_1_bit.back ();
+    return;
+  }
+
+  size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta);
+  *l_bit_0 = d_metric_table_0_bit[l_ndx];
+  *l_bit_1 = d_metric_table_1_bit[l_ndx];
+}
+
+void code_metric_fl::convert
+(size_t n_syms,
+ pdf_fcn_io_t* sym,
+ void* bit_0,
+ void* bit_1)
+{
+  metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
+  metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
+
+  for (size_t m = n_syms; m > 0; m--)
+    lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
+}
+
+code_metric_fs::code_metric_fs (pdf_fcn_t pdf_fcn_0_bit,
+                                 pdf_fcn_t pdf_fcn_1_bit,
+                                 size_t n_samples,
+                                 pdf_fcn_io_t min_sample,
+                                 pdf_fcn_io_t max_sample,
+                                 int sample_precision)
+{
+  if (n_samples < 2) {
+    fprintf (stderr, "code_metric_fs:: n_samples "
+            "must be at least 2.\n");
+    assert (0);
+  }
+  if (min_sample >= max_sample) {
+    fprintf (stderr, "code_metric_fs:: min_sample must be "
+            "less than max_sample.\n");
+    assert (0);
+  }
+  if (! pdf_fcn_0_bit) {
+    fprintf (stderr, "code_metric_fs:: pdf_fcn_0_bit must be "
+            "a non-null pointer to function.\n");
+    assert (0);
+  }
+  if (! pdf_fcn_1_bit) {
+    fprintf (stderr, "code_metric_fs:: pdf_fcn_0_bit must be "
+            "a non-null pointer to function.\n");
+    assert (0);
+  }
+  if (sample_precision < 9 || sample_precision > 16) {
+    fprintf (stderr, "code_metric_fs:: sample_precision must be "
+            "between 9 and 16 for this class.\n");
+    assert (0);
+  }
+
+  d_sample_precision = sample_precision;
+  d_n_samples = n_samples;
+  d_max_sample = max_sample;
+  d_min_sample = min_sample;
+  d_delta = (max_sample - min_sample) / (n_samples - 1);
+  d_pdf_fcn_0_bit = pdf_fcn_0_bit;
+  d_pdf_fcn_1_bit = pdf_fcn_1_bit;
+  d_metric_table_0_bit.assign (n_samples, 0);
+  d_metric_table_1_bit.assign (n_samples, 0);
+
+// get the scale factor for converting from float to sample_precision
+// maps:
+//    logf (pdf_fcn_0_bit->eval (d_min_sample))  ->  l_min_map
+//    logf (pdf_fcn_0_bit->eval (d_max_sample))  ->  l_max_map
+
+  metric_t l_min_map = - (1 << (sample_precision - 1));
+
+  pdf_fcn_io_t l_min_log_val_0 = logf ((*pdf_fcn_0_bit)(d_min_sample));
+  pdf_fcn_io_t l_max_log_val_0 = logf ((*pdf_fcn_0_bit)(d_max_sample));
+  pdf_fcn_io_t l_slope_0 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
+                           (l_max_log_val_0 - l_min_log_val_0));
+  pdf_fcn_io_t l_min_log_val_1 = logf ((*pdf_fcn_1_bit)(d_min_sample));
+  pdf_fcn_io_t l_max_log_val_1 = logf ((*pdf_fcn_1_bit)(d_max_sample));
+  pdf_fcn_io_t l_slope_1 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
+                           (l_max_log_val_1 - l_min_log_val_1));
+
+  pdf_fcn_io_t l_val = d_min_sample;
+  for (size_t m = 0; m < d_n_samples; m++) {
+    d_metric_table_0_bit[m] =
+      (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
+                        (l_slope_0 * (logf ((*pdf_fcn_0_bit)(l_val)) -
+                                      l_min_log_val_0)));
+    d_metric_table_1_bit[m] =
+      (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
+                        (l_slope_1 * (logf ((*pdf_fcn_1_bit)(l_val)) -
+                                      l_min_log_val_1)));
+    l_val += d_delta;
+  }
+}
+
+void code_metric_fs::lookup
+(pdf_fcn_io_t sym,
+ void* bit_0,
+ void* bit_1)
+{
+  metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
+  metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
+
+  if (sym <= d_min_sample) {
+    *l_bit_0 = d_metric_table_0_bit[0];
+    *l_bit_1 = d_metric_table_1_bit[0];
+    return;
+  }
+  if (sym >= d_max_sample) {
+    *l_bit_0 = d_metric_table_0_bit.back ();
+    *l_bit_1 = d_metric_table_1_bit.back ();
+    return;
+  }
+
+  size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta);
+  *l_bit_0 = d_metric_table_0_bit[l_ndx];
+  *l_bit_1 = d_metric_table_1_bit[l_ndx];
+}
+
+void code_metric_fs::convert
+(size_t n_syms,
+ pdf_fcn_io_t* sym,
+ void* bit_0,
+ void* bit_1)
+{
+  metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
+  metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
+
+  for (size_t m = n_syms; m > 0; m--)
+    lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
+}
+
+code_metric_fb::code_metric_fb (pdf_fcn_t pdf_fcn_0_bit,
+                                 pdf_fcn_t pdf_fcn_1_bit,
+                                 size_t n_samples,
+                                 pdf_fcn_io_t min_sample,
+                                 pdf_fcn_io_t max_sample,
+                                 int sample_precision)
+{
+  if (n_samples < 2) {
+    fprintf (stderr, "code_metric_fb:: n_samples "
+            "must be at least 2.\n");
+    assert (0);
+  }
+  if (min_sample >= max_sample) {
+    fprintf (stderr, "code_metric_fb:: min_sample must be "
+            "less than max_sample.\n");
+    assert (0);
+  }
+  if (! pdf_fcn_0_bit) {
+    fprintf (stderr, "code_metric_fb:: pdf_fcn_0_bit must be "
+            "a non-null pointer to function.\n");
+    assert (0);
+  }
+  if (! pdf_fcn_1_bit) {
+    fprintf (stderr, "code_metric_fb:: pdf_fcn_0_bit must be "
+            "a non-null pointer to function.\n");
+    assert (0);
+  }
+  if (sample_precision < 1 || sample_precision > 8) {
+    fprintf (stderr, "code_metric_fb:: sample_precision must be "
+            "between 1 and 8 for this class.\n");
+    assert (0);
+  }
+
+  d_sample_precision = sample_precision;
+  d_n_samples = n_samples;
+  d_max_sample = max_sample;
+  d_min_sample = min_sample;
+  d_delta = (max_sample - min_sample) / (n_samples - 1);
+  d_pdf_fcn_0_bit = pdf_fcn_0_bit;
+  d_pdf_fcn_1_bit = pdf_fcn_1_bit;
+  d_metric_table_0_bit.assign (n_samples, 0);
+  d_metric_table_1_bit.assign (n_samples, 0);
+
+// get the scale factor for converting from float to sample_precision
+// maps:
+//    logf (pdf_fcn_0_bit->eval (d_min_sample))  ->  l_min_map
+//    logf (pdf_fcn_0_bit->eval (d_max_sample))  ->  l_max_map
+
+  metric_t l_min_map = - (1 << (sample_precision - 1));
+
+  pdf_fcn_io_t l_min_log_val_0 = logf ((*pdf_fcn_0_bit)(d_min_sample));
+  pdf_fcn_io_t l_max_log_val_0 = logf ((*pdf_fcn_0_bit)(d_max_sample));
+  pdf_fcn_io_t l_slope_0 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
+                           (l_max_log_val_0 - l_min_log_val_0));
+  pdf_fcn_io_t l_min_log_val_1 = logf ((*pdf_fcn_1_bit)(d_min_sample));
+  pdf_fcn_io_t l_max_log_val_1 = logf ((*pdf_fcn_1_bit)(d_max_sample));
+  pdf_fcn_io_t l_slope_1 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
+                           (l_max_log_val_1 - l_min_log_val_1));
+
+  pdf_fcn_io_t l_val = d_min_sample;
+  for (size_t m = 0; m < d_n_samples; m++) {
+    d_metric_table_0_bit[m] =
+      (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
+                        (l_slope_0 * (logf ((*pdf_fcn_0_bit)(l_val)) -
+                                      l_min_log_val_0)));
+    d_metric_table_1_bit[m] =
+      (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
+                        (l_slope_1 * (logf ((*pdf_fcn_1_bit)(l_val)) -
+                                      l_min_log_val_1)));
+    l_val += d_delta;
+  }
+}
+
+void code_metric_fb::lookup
+(pdf_fcn_io_t sym,
+ void* bit_0,
+ void* bit_1)
+{
+  metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
+  metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
+
+  if (sym <= d_min_sample) {
+    *l_bit_0 = d_metric_table_0_bit[0];
+    *l_bit_1 = d_metric_table_1_bit[0];
+    return;
+  }
+  if (sym >= d_max_sample) {
+    *l_bit_0 = d_metric_table_0_bit.back ();
+    *l_bit_1 = d_metric_table_1_bit.back ();
+    return;
+  }
+
+  size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta);
+  *l_bit_0 = d_metric_table_0_bit[l_ndx];
+  *l_bit_1 = d_metric_table_1_bit[l_ndx];
+}
+
+void code_metric_fb::convert
+(size_t n_syms,
+ pdf_fcn_io_t* sym,
+ void* bit_0,
+ void* bit_1)
+{
+  metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
+  metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
+
+  for (size_t m = n_syms; m > 0; m--)
+    lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
+}

Index: code_metrics.h
===================================================================
RCS file: code_metrics.h
diff -N code_metrics.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ code_metrics.h      3 Jul 2006 02:14:12 -0000       1.1
@@ -0,0 +1,154 @@
+/* -*- c++ -*- */
+/*
+ * Copyright @ 2006 Michael Dickens
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this library; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef INCLUDED_CODE_METRIC_H
+#define INCLUDED_CODE_METRIC_H
+
+#include <sys/types.h>
+#include <vector>
+#include <assert.h>
+
+class code_metrics
+{
+public:
+  typedef float pdf_fcn_io_t;
+
+  code_metrics () {};
+  virtual ~code_metrics () {};
+
+// lookup() returns either a float, or a sign-extended
+// 'sample_precision'-bit integer value.
+
+  virtual void lookup (pdf_fcn_io_t sym,
+                      void* bit_0,
+                      void* bit_1) = 0;
+
+  virtual void convert (size_t n_syms,
+                       pdf_fcn_io_t* syms,
+                       void* bit_0,
+                       void* bit_1) = 0;
+};
+
+class code_metric_ff : public code_metrics
+{
+  typedef pdf_fcn_io_t (*pdf_fcn_t) (pdf_fcn_io_t);
+  typedef float metric_t, *metric_ptr_t;
+
+private:
+  size_t d_n_samples;
+  pdf_fcn_io_t d_max_sample, d_min_sample, d_delta;
+  pdf_fcn_t d_pdf_fcn_0_bit, d_pdf_fcn_1_bit;
+  std::vector<metric_t> d_metric_table_0_bit;
+  std::vector<metric_t> d_metric_table_1_bit;
+
+public:
+  code_metric_ff (pdf_fcn_t pdf_fcn_0_bit,
+                 pdf_fcn_t pdf_fcn_1_bit,
+                 size_t n_samples,
+                 pdf_fcn_io_t min_sample,
+                 pdf_fcn_io_t max_sample);
+  ~code_metric_ff () {};
+
+  void lookup (pdf_fcn_io_t sym, void* bit_0, void* bit_1);
+  void convert (size_t n_syms, pdf_fcn_io_t* sym, void* bit_0, void* bit_1);
+};
+
+class code_metric_fl : public code_metrics
+{
+  typedef float pdf_fcn_io_t;
+  typedef pdf_fcn_io_t (*pdf_fcn_t) (pdf_fcn_io_t);
+  typedef long metric_t, *metric_ptr_t;
+
+private:
+  char d_sample_precision;
+  size_t d_n_samples, d_sample_mask;
+  pdf_fcn_io_t d_max_sample, d_min_sample, d_delta;
+  pdf_fcn_t d_pdf_fcn_0_bit, d_pdf_fcn_1_bit;
+  std::vector<metric_t> d_metric_table_0_bit;
+  std::vector<metric_t> d_metric_table_1_bit;
+
+public:
+  code_metric_fl (pdf_fcn_t pdf_fcn_0_bit,
+                 pdf_fcn_t pdf_fcn_1_bit,
+                 size_t n_samples,
+                 pdf_fcn_io_t min_sample,
+                 pdf_fcn_io_t max_sample,
+                 int sample_precision = 32);
+  ~code_metric_fl () {};
+
+  void lookup (pdf_fcn_io_t sym, void* bit_0, void* bit_1);
+  void convert (size_t n_syms, pdf_fcn_io_t* sym, void* bit_0, void* bit_1);
+};
+
+class code_metric_fs : public code_metrics
+{
+  typedef float pdf_fcn_io_t;
+  typedef pdf_fcn_io_t (*pdf_fcn_t) (pdf_fcn_io_t);
+  typedef short metric_t, *metric_ptr_t;
+
+private:
+  char d_sample_precision;
+  size_t d_n_samples, d_sample_mask;
+  pdf_fcn_io_t d_max_sample, d_min_sample, d_delta;
+  pdf_fcn_t d_pdf_fcn_0_bit, d_pdf_fcn_1_bit;
+  std::vector<metric_t> d_metric_table_0_bit;
+  std::vector<metric_t> d_metric_table_1_bit;
+
+public:
+  code_metric_fs (pdf_fcn_t pdf_fcn_0_bit,
+                 pdf_fcn_t pdf_fcn_1_bit,
+                 size_t n_samples,
+                 pdf_fcn_io_t min_sample,
+                 pdf_fcn_io_t max_sample,
+                 int sample_precision = 16);
+  ~code_metric_fs () {};
+
+  void lookup (pdf_fcn_io_t sym, void* bit_0, void* bit_1);
+  void convert (size_t n_syms, pdf_fcn_io_t* sym, void* bit_0, void* bit_1);
+};
+
+class code_metric_fb : public code_metrics
+{
+  typedef float pdf_fcn_io_t;
+  typedef pdf_fcn_io_t (*pdf_fcn_t) (pdf_fcn_io_t);
+  typedef char metric_t, *metric_ptr_t;
+
+private:
+  char d_sample_precision;
+  size_t d_n_samples, d_sample_mask;
+  pdf_fcn_io_t d_max_sample, d_min_sample, d_delta;
+  pdf_fcn_t d_pdf_fcn_0_bit, d_pdf_fcn_1_bit;
+  std::vector<metric_t> d_metric_table_0_bit;
+  std::vector<metric_t> d_metric_table_1_bit;
+
+public:
+  code_metric_fb (pdf_fcn_t pdf_fcn_0_bit,
+                 pdf_fcn_t pdf_fcn_1_bit,
+                 size_t n_samples,
+                 pdf_fcn_io_t min_sample,
+                 pdf_fcn_io_t max_sample,
+                 int sample_precision = 8);
+  ~code_metric_fb () {};
+
+  void lookup (pdf_fcn_io_t sym, void* bit_0, void* bit_1);
+  void convert (size_t n_syms, pdf_fcn_io_t* sym, void* bit_0, void* bit_1);
+};
+
+#endif /* INCLUDED_CODE_METRIC_H */

Index: encoder.h
===================================================================
RCS file: encoder.h
diff -N encoder.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ encoder.h   3 Jul 2006 02:14:12 -0000       1.1
@@ -0,0 +1,56 @@
+/* -*- c++ -*- */
+/*
+ * Copyright @ 2006 Michael Dickens
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this library; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef INCLUDED_ENCODER_H
+#define INCLUDED_ENCODER_H
+
+#include <sys/types.h>
+
+// the following is the type used for encoder memory
+
+typedef unsigned long memory_t, *memory_ptr_t;
+
+// the 'encoder' class is a virtual class upon which all encoder types
+// can be built.
+
+class encoder
+{
+public:
+  encoder () {};
+  virtual ~encoder () {};
+
+  virtual size_t compute_n_input_bits (size_t n_output_bits) = 0;
+  virtual size_t compute_n_output_bits (size_t n_input_bits) = 0;
+  virtual size_t encode (const char** in_buf,
+                        char** out_buf,
+                        size_t n_bits_to_output) = 0;
+  virtual size_t encode (const char** in_buf,
+                        size_t n_bits_to_input,
+                        char** out_buf) = 0;
+
+  size_t d_frame_size_bits, d_n_code_inputs, d_n_code_outputs;
+  size_t d_max_memory, d_n_enc_bits;
+  memory_t d_max_mem_mask;
+  memory_t d_in_buf_ndx, d_out_buf_ndx;
+  memory_t d_in_bit_shift, d_out_bit_shift;
+  size_t d_n_input_bits_left, d_n_output_bits_left;
+};
+
+#endif /* INCLUDED_ENCODER_H */

Index: encoder_convolutional.cc
===================================================================
RCS file: encoder_convolutional.cc
diff -N encoder_convolutional.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ encoder_convolutional.cc    3 Jul 2006 02:14:12 -0000       1.1
@@ -0,0 +1,640 @@
+/* -*- c++ -*- */
+/*
+ * Copyright @ 2006 Michael Dickens
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this library; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <encoder_convolutional.h>
+#include <assert.h>
+#include <iostream>
+
+#define DO_TIME_THOUGHPUT 1
+#define DO_PRINT_DEBUG 1
+
+#if DO_TIME_THOUGHPUT
+#include <mld/mld_timer.h>
+#endif
+#if DO_PRINT_DEBUG
+#include <mld/n2bs.h>
+#endif
+
+static const int g_max_frame_size_bits = 10000000;
+static const int g_max_num_streams = 10;
+static const int g_num_bits_per_byte = 8;
+
+// sum the number of set bits, mod 2, for the output bit
+char sum_bits_mod2 (memory_t in_mem, size_t max_memory)
+{
+// there are faster ways to do this, but this works for now; could
+// certainly do a single inline asm, which most processors provide to
+// deal with summing the bits in an integer
+
+  char t_out_bit = (char)(in_mem & 1);
+  for (size_t r = max_memory; r > 0; r--) {
+    in_mem >>= 1;
+    t_out_bit ^= ((char)(in_mem & 1));
+  }
+  return (t_out_bit);
+}
+
+encoder_convolutional::encoder_convolutional
+(int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ std::vector<int> &code_generators,
+ int start_memory_state,
+ int end_memory_state,
+ bool do_termination,
+ bool use_muxed_inputs,
+ bool do_muxed_outputs,
+ bool use_packed_input,
+ bool do_packed_outputs)
+{
+// make sure the frame length makes sense
+  if ((frame_size_bits < 0) | (frame_size_bits > g_max_frame_size_bits)) {
+    std::cerr << "encoder_convolutional: " <<
+      "Requested frame length (" << frame_size_bits <<
+      " bits) must be between 0 and " << g_max_frame_size_bits <<
+      " bits, with 0 being a streaming encoder.\n";
+    assert (0);
+  }
+
+// check to make sure the number of input streams makes sense
+  if ((n_code_inputs <= 0) | (n_code_inputs > g_max_num_streams)) {
+    std::cerr << "encoder_convolutional: " <<
+      "Requested number of input streams (" <<
+      n_code_inputs << ") must be between 1 and " <<
+      g_max_num_streams << ".\n";
+    assert (0);
+  }
+
+// check to make sure the number of output streams makes sense
+  if ((n_code_outputs <= 0) | (n_code_outputs > g_max_num_streams)) {
+    std::cerr << "encoder_convolutional: " <<
+      "Requested number of output streams (" <<
+      n_code_outputs << ") must be between 1 and " <<
+      g_max_num_streams << ".\n";
+    assert (0);
+  }
+
+// make sure the code_generator is the correct length
+  if (code_generators.size () !=
+      ((size_t)(n_code_inputs * n_code_outputs))) {
+    std::cerr << "encoder_convolutional: " <<
+      "Number of code generator entries (" << code_generators.size () <<
+      ") is not equal to the product of the number of input and output" <<
+      " streams (" << (n_code_inputs * n_code_outputs) << ").\n";
+    assert (0);
+  }
+
+// create the class frame variables
+  d_frame_size_bits = frame_size_bits;
+  d_n_code_inputs = n_code_inputs;
+  d_n_code_outputs = n_code_outputs;
+  d_do_streaming = (frame_size_bits == 0);
+  d_do_termination = (d_do_streaming == true) ? false : do_termination;
+  d_use_muxed_inputs = use_muxed_inputs;
+  d_do_muxed_outputs = do_muxed_outputs;
+  d_use_packed_input = use_packed_input;
+  d_do_packed_outputs = do_packed_outputs;
+
+// allocate the vectors for doing the encoding.  use 32-bit int's
+// actual bits to represent memory and the code, as it makes the
+// operations quite simple the state vectors.
+// states are per each input,
+// code generates are for each I/O combination
+
+  d_states.assign (d_n_code_inputs, 0);
+  d_init_states.assign (d_n_code_inputs, 0);
+  d_term_states.assign (d_n_code_inputs, 0);
+  d_code_generators.assign (d_n_code_inputs * d_n_code_outputs, 0);
+
+// FIXME:  STILL NEED TO COPY OVER START AND END MEMORY STATES;
+
+// check the input code_generator for correctness & find the memory order
+// t_max_mem will be the mamimum number of memories used by the generator
+// t_code_ndx is a counter over all input code_generator elements
+  size_t t_max_mem = 0, t_code_ndx = d_code_generators.size() - 1;
+// loop over all input streams first, output streams second
+  for (int n = d_n_code_outputs - 1; n >= 0; n--) {
+    size_t t_all_inputs_zero = 0;
+    for (int m = d_n_code_inputs - 1; m >= 0; m--) {
+      size_t t_in_code = code_generators[t_code_ndx];
+      t_all_inputs_zero |= t_in_code;
+      size_t t_code_mem = 0;
+// find the memory requirement for this code generator
+      while (t_in_code != 0) {
+       t_in_code >>= 1;
+       t_code_mem++;
+      }
+      if (t_code_mem > t_max_mem)
+       t_max_mem = t_code_mem;
+// store in d_code_generators in output-first ordering
+      d_code_generators[(m*d_n_code_outputs) + n] =
+       code_generators[t_code_ndx--];
+    }
+    if (t_all_inputs_zero == 0) {
+      std::cerr << "encoder_convolutional: " <<
+       "At least 1 generator code for output " << n+1 <<
+       " must be non-0.\n";
+      assert (0);
+    }
+  }
+
+// store the maximum memory order (e.g. "2" -> D^2)
+  d_max_memory = t_max_mem - 1;
+
+// make sure the frame length makes sense, #2
+  if ((d_frame_size_bits != 0) & (d_frame_size_bits < d_max_memory)) {
+    std::cerr << "encoder_convolutional: " <<
+      "Requested frame length (" << d_frame_size_bits <<
+      " bit" << (d_frame_size_bits > 1 ? "s" : "") <<
+      ") must be at least 1 constraint length (" << d_max_memory <<
+      " bit" << (d_max_memory > 1 ? "s" : "") <<
+      " for this code) when doing block coding.\n";
+    assert (0);
+  }
+
+// create the memory mask for this code generator
+  d_max_mem_mask = (2 << d_max_memory) - 1;
+
+// set the initial FSM state to 'init'
+  d_fsm_state = fsm_enc_conv_init;
+
+// debugging from here down
+#if DO_PRINT_DEBUG
+  std::cout << "Encoder:\n  Mask = " <<
+    n2bs (d_max_mem_mask, d_max_memory+2) <<
+    "\n  Max_Mem = " << d_max_memory << "\n.";
+#endif
+}
+
+size_t
+encoder_convolutional::compute_n_output_bits
+(size_t n_input_bits)
+{
+  return (0);
+}
+
+/*
+ * Compute the number of input bits needed to produce
+ * 'n_output' bits.  For convolutional encoders, there is
+ * 1 bit output per bit input per stream, with the addition of a some
+ * bits for trellis termination if selected.  Thus the input:output
+ * bit ratio will be:
+ * 
+ * if (streaming | no termination), 1:1
+ *
+ * if (not streaming & termination), roughly 1:(1+X), where "X" is the
+ * total memory size of the code divided by the block length in bits.
+ * But this also depends on the state of the FSM ... how many bits are
+ * left before termination.
+ *
+ * The returned value will also depend on whether bits are packed, as
+ * well as whether streams are mux'ed together.
+ */
+
+size_t
+encoder_convolutional::compute_n_input_bits
+(size_t n_output_bits)
+{
+  size_t t_n_output_bits, t_n_input_bits;
+  t_n_output_bits = t_n_input_bits = n_output_bits;
+
+  if (d_do_termination == true) {
+// not streaming, doing termination
+// find the number of bits currently available with no required inputs, if any
+    size_t n_extra = 0;
+    if (d_fsm_state == fsm_enc_conv_doing_term) {
+      n_extra = d_max_memory - d_n_enc_bits;
+    }
+
+// check to see if this is enough; return 0 if it is.
+    if (n_extra >= t_n_output_bits)
+      return (0);
+
+// remove those which require no input
+    t_n_output_bits -= n_extra;
+
+// find the number of frames of data which could be processed
+    size_t t_n_output_bits_per_frame = d_frame_size_bits + d_max_memory;
+
+// get the base number of input items required for the given number of
+// frames to be generated
+    size_t t_n_frames = t_n_output_bits / t_n_output_bits_per_frame;
+    t_n_input_bits = t_n_frames * d_frame_size_bits;
+
+// add to that the number of leftover inputs needed to generate the
+// remainder of the outputs within the remaining frame, up to the
+// given frame size (since anything beyond that within this frame
+// requires no inputs)
+    size_t t_leftover_bits = t_n_output_bits % t_n_output_bits_per_frame;
+    t_n_input_bits += ((t_leftover_bits > d_frame_size_bits) ?
+                      d_frame_size_bits : t_leftover_bits);
+  }
+
+  return (t_n_input_bits);
+}
+
+size_t
+encoder_convolutional::encode (const char** in_buf,
+                              char** out_buf,
+                              size_t n_bits_to_output)
+{
+// set the class-internal number of input and
+// output bits left to encode
+  size_t saved_n_input_bits;
+  saved_n_input_bits = d_n_input_bits_left =
+    compute_n_input_bits (n_bits_to_output);
+  d_n_output_bits_left = n_bits_to_output;
+
+// call the private encode function
+  encode_private (in_buf, out_buf);
+
+#ifdef DO_PRINT_DEBUG
+  std::cout << "n_input_bits_used = " <<
+    (saved_n_input_bits - d_n_input_bits_left) << '\n';
+  std::cout << "n_output_bits_used = " <<
+    (n_bits_to_output - d_n_output_bits_left) << '\n';
+
+  assert (d_out_buf_ndx == n_bits_to_output);
+#endif
+
+// return the actual number of input bits used
+  return (saved_n_input_bits - d_n_input_bits_left);
+}
+
+/*
+ * encode a certain number of input bits
+ *
+ * the 'in_buf' and 'out_buf' must have enough memory to handle the
+ * number of input and output bits; no error checking is done!
+ *
+ * n_bits_to_input: is the number of input bits per input stream to encode
+ *
+ * returns the number of actual bits written to the output stream(s)
+ */
+
+size_t
+encoder_convolutional::encode (const char** in_buf,    
+                              size_t n_bits_to_input,
+                              char** out_buf)
+{
+// set the class-internal number of input and
+// output bits left to encode
+  size_t saved_n_output_bits;
+  saved_n_output_bits = d_n_output_bits_left =
+    compute_n_output_bits (n_bits_to_input);
+  d_n_input_bits_left = n_bits_to_input;
+
+// call the private encode function
+  encode_private (in_buf, out_buf);
+
+#ifdef DO_PRINT_DEBUG
+  std::cout << "n_input_bits_used = " <<
+    (n_bits_to_input - d_n_input_bits_left) << '\n';
+  std::cout << "n_output_bits_used = " <<
+    (saved_n_output_bits - d_n_output_bits_left) << '\n';
+
+  assert (d_in_buf_ndx == n_bits_to_input);
+#endif
+
+// return the actual number of input bits used
+  return (saved_n_output_bits - d_n_output_bits_left);
+}
+
+void
+encoder_convolutional::encode_private (const char** in_buf,
+                                      char** out_buf)
+{
+#if DO_TIME_THOUGHPUT
+  struct timeval t_tp;
+  start_timer (&t_tp);
+#endif
+
+// reset buffer indices
+  d_in_buf_ndx = d_out_buf_ndx = d_in_bit_shift = d_out_bit_shift = 0;
+
+#if DO_PRINT_DEBUG
+  std::cout << "Beginning this encode() call; starting parameters.\n";
+  std::cout << "d_n_input_bits_left = " << d_n_input_bits_left << '\n';
+  std::cout << "d_n_output_bits_left = " << d_n_output_bits_left << '\n';
+#endif
+
+// while there are inputs and outputs left to process ...
+  while ((d_n_input_bits_left != 0) & (d_n_output_bits_left != 0)) {
+
+// jump to the correct state in the fsm
+    switch (d_fsm_state) {
+
+    case fsm_enc_conv_init:
+// copy the init states to the current states
+      d_states = d_init_states;
+// if not doing streaming, things to do; else nothing more do
+      if (d_do_streaming == false) {
+// reset the number of encoded bits in this block (which is used to
+// compare with the number of bits in the frame)
+       d_n_enc_bits = 0;
+      }
+// move to the 'up' state
+      d_fsm_state = fsm_enc_conv_doing_up;
+      break;
+
+    case fsm_enc_conv_doing_up:
+// starting the trellis;
+// loop up to the max memory, counting down the number of input bits left
+      encode_loop (in_buf, out_buf, &d_n_input_bits_left, d_max_memory);
+
+// finished this loop; check for jumping to the next state
+      if (d_n_enc_bits == d_max_memory)
+       d_fsm_state = fsm_enc_conv_doing_middle;
+      break;
+
+    case fsm_enc_conv_doing_middle:
+// middle of the trellis;
+// loop up to the frame size (before termination bits, if any),
+// counting down the number of input bits
+      encode_loop (in_buf, out_buf, &d_n_input_bits_left, d_frame_size_bits);
+
+// finished this loop; check for jumping to the next state
+      if ((d_n_enc_bits == d_frame_size_bits) & (d_do_streaming == false)) {
+// jump to another state, depending on termination requirement
+       if (d_do_termination == true) {
+         d_n_enc_bits = 0;
+         d_fsm_state = fsm_enc_conv_doing_term;
+       } else {
+         d_fsm_state = fsm_enc_conv_init;
+       }
+      }
+      break;
+
+    case fsm_enc_conv_doing_term:
+// terminating the trellis;
+// better get here only when do_termination is true, but check just in case;
+// lopp up to the max memory, counting down the number of output bits left
+      if (d_do_termination == false) {
+       encode_loop (in_buf, out_buf, &d_n_output_bits_left, d_max_memory);
+
+// finished this loop; check for jumping to the next state
+       if (d_n_enc_bits == d_max_memory)
+         d_fsm_state = fsm_enc_conv_init;
+      } else {
+// should never get here!
+       assert (0);
+      }
+      break;
+
+    default:
+// better never get here!
+      assert (0);
+      break;
+
+// done (switch) with FSM
+    }
+
+// done (while) there are inputs and outputs
+  }
+
+#if DO_PRINT_DEBUG
+  std::cout << "Done with this encode() call; ending parameters.\n";
+  std::cout << "d_in_bit_shift = " << d_in_bit_shift << '\n';
+  std::cout << "d_out_bit_shift = " << d_out_bit_shift << '\n';
+  std::cout << "d_in_buf_ndx = " << d_in_buf_ndx << '\n';
+  std::cout << "d_out_buf_ndx = " << d_out_buf_ndx << '\n';
+  std::cout << "d_n_input_bits_left = " << d_n_input_bits_left << '\n';
+  std::cout << "d_n_output_bits_left = " << d_n_output_bits_left << '\n';
+#endif
+
+#if DO_TIME_THOUGHPUT
+  u_long d_t = end_timer (&t_tp);
+
+#if 1
+  std::cout << "Completed " << d_in_buf_ndx <<
+    " bits in " << d_t << " usec => " <<
+    1e6*(((double) d_in_buf_ndx)/((double) d_t)) <<
+    " b/s\n";
+#else
+  std::cout << "Completed " << (d_in_buf_ndx * g_num_bits_per_byte) <<
+    " bits in " << d_t << " usec => " <<
+    1e6*(((double)(d_in_buf_ndx * g_num_bits_per_byte))/((double) d_t)) <<
+    " b/s\n";
+#endif
+#endif
+}
+
+void
+encoder_convolutional::encode_loop
+(const char** in_buf, char** out_buf, size_t* which_counter, size_t how_many)
+{
+  while (((*which_counter) > 0) & (d_n_enc_bits < how_many)) {
+// get the new inputs, one bit per stream, and update the state to
+// reflect these inputs
+
+// loop over all inputs, push the current state bit into d_states
+    memory_ptr_t t_states_ptr = &(d_states[0]);
+    for (size_t p = 0; p < d_n_code_inputs; p++) {
+      memory_t t_state = ((*t_states_ptr) << 1) & d_max_mem_mask;
+
+#if DO_PRINT_DEBUG
+      char t_new_input_bit = get_new_input_bit (in_buf, p);
+      t_state |= t_new_input_bit;
+#else
+      t_state |= get_new_input_bit (in_buf, p);
+#endif
+
+#if DO_PRINT_DEBUG
+      std::cout << "I[" << p << "][" << d_in_buf_ndx << "] = ";
+      cout_binary (in_buf[p][d_in_buf_ndx], g_num_bits_per_byte);
+      std::cout << ", st_i[" << p << "] = ";
+      cout_binary ((*t_states_ptr), d_max_memory+2);
+      std::cout << ", I[" << p << "][" << d_in_buf_ndx << "][" <<
+       d_in_bit_shift << "] = " << t_new_input_bit <<
+       ", st_o[" << p << "] = ";
+      cout_binary (t_state, d_max_memory+2);
+      std::cout << '\n';
+#endif
+
+      (*t_states_ptr++) = t_state;
+    }
+
+// now encode those inputs using the code generators,
+// and output a single bit per output stream
+
+#if DO_PRINT_DEBUG
+    size_t t_vec_ctr = 0;
+#endif
+
+    memory_ptr_t t_code_generators = &(d_code_generators[0]);
+// loop over all outputs
+    for (size_t q = 0; q < d_n_code_outputs; q++) {
+      memory_t t_out_result = 0;
+      t_states_ptr = &(d_states[0]);
+
+// loop over all inputs, xor'ing the result each time
+      for (size_t p = 0; p < d_n_code_inputs; p++) {
+
+#if DO_PRINT_DEBUG
+       std::cout << "b_i = " <<
+         n2bs (t_out_result, d_max_memory+2) << ", st[" << p << "] = " <<
+         n2bs (*t_states_ptr, d_max_memory+2) << ", cg[" << t_vec_ctr++ <<
+         "] = " << n2bs (*t_code_generators, d_max_memory+2) <<
+         ", st[] & cg[] = " <<
+         n2bs ((*t_states_ptr) & (*t_code_generators), d_max_memory+2);
+#endif
+
+       t_out_result ^= ((*t_states_ptr++) & (*t_code_generators++));
+
+#if DO_PRINT_DEBUG
+       std::cout << ", b_o = " << n2bs (t_out_result, d_max_memory+2) << '\n';
+#endif
+      }
+#if DO_PRINT_DEBUG
+      std::cout << "b_r = " << n2bs (t_out_result, d_max_memory+2);
+#endif
+// sum the number of set bits, mod 2, for the output bit
+      char t_out_bit = sum_bits_mod2 (t_out_result, d_max_memory);
+
+// output this particular bit on this output stream
+      output_bit (t_out_bit, out_buf, q);
+
+// increment the input and output counters, if necessary, between output bits
+      increment_counters (true);
+    }
+
+// increment the input and output counters, if necessary, between input bits
+    increment_counters (false);
+
+// increment the number of encoded bits for the current block
+    d_n_enc_bits++;
+
+// decrement the number of input and output bits left
+    d_n_input_bits_left--;
+    d_n_output_bits_left--;
+  }
+}
+
+void
+encoder_convolutional::increment_counters (bool while_encoding)
+{
+// increment the buffer index only for this version, only after encoding
+// is done and all resulting outputs are stored on the output streams
+  if (while_encoding == false) {
+    d_out_buf_ndx++;
+// increment the input buffer index only for this version
+    d_in_buf_ndx++;
+  }
+#if 0
+// move counters to the next input bit, wrapping to the next input
+// byte as necessary
+  if (++d_in_bit_shift % g_num_bits_per_byte == 0) {
+    d_in_bit_shift = 0;
+    d_in_buf_ndx++;
+  }
+// move counters to the next output bit, wrapping to the next output
+// byte as necessary
+    if (++d_out_bit_shift % g_num_bits_per_byte == 0) {
+      d_out_bit_shift = 0;
+      d_out_buf_ndx++;
+    }
+#endif
+}
+
+void
+encoder_convolutional::output_bit (char t_out_bit,
+                                  char** out_buf,
+                                  size_t t_output_stream)
+{
+// store the result for this particular output stream
+
+#if DO_PRINT_DEBUG
+  std::cout << ", O_i[" << t_output_stream <<
+    "][" << d_out_buf_ndx << "] = " <<
+    n2bs (out_buf[t_output_stream][d_out_buf_ndx], g_num_bits_per_byte);
+#endif
+
+// one bit per output item
+  out_buf[t_output_stream][d_out_buf_ndx] = t_out_bit;
+
+#if 0
+// packed bits in each output item
+  out_buf[t_output_stream][d_out_buf_ndx] |=
+    (t_out_bit << d_out_bit_shift);
+#endif
+
+#if DO_PRINT_DEBUG
+  std::cout << ", b_out = " << t_out_bit <<
+    ", O_o[" << t_output_stream << "][" << d_out_buf_ndx << "][" <<
+    d_out_bit_shift << "] = " <<
+    n2bs (out_buf[t_output_stream][d_out_buf_ndx], g_num_bits_per_byte) << 
'\n';
+#endif
+}
+
+char
+encoder_convolutional::get_new_input_bit__up (const char** in_buf,
+                                             size_t code_input_n)
+{
+  return (get_new_input_bit__middle (in_buf, code_input_n));
+}
+
+char
+encoder_convolutional::get_new_input_bit__middle (const char** in_buf,
+                                                 size_t code_input_n)
+{
+  return (in_buf[code_input_n][d_in_buf_ndx] & 1);
+
+#if 0
+// if doing packed, should probably allow user to select how
+// bits are selected, so-as to make sure it's always the same
+// no matter the CPU endianness
+   return ((in_buf[code_input_n][d_in_buf_ndx] >> d_in_bit_shift) & 1);
+#endif
+}
+
+char
+encoder_convolutional::get_new_input_bit__term (size_t code_input_n)
+{
+  return (d_term_states[code_input_n] & 1);
+
+#if 0
+  return ((d_term_states[code_input_n] >> d_in_bit_shift) & 1);
+#endif
+}
+
+char
+encoder_convolutional::get_new_input_bit (const char** in_buf,
+                                         size_t code_input_n)
+{
+  char ret_val = 0;
+  switch (d_fsm_state) {
+  case fsm_enc_conv_doing_up:
+    ret_val = get_new_input_bit__up (in_buf, code_input_n);
+    break;
+  case fsm_enc_conv_doing_middle:
+    ret_val = get_new_input_bit__middle (in_buf, code_input_n);
+    break;
+  case fsm_enc_conv_doing_term:
+    ret_val = get_new_input_bit__term (code_input_n);
+    break;
+  default:
+    break;
+  }
+  return (ret_val);
+}

Index: encoder_convolutional.h
===================================================================
RCS file: encoder_convolutional.h
diff -N encoder_convolutional.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ encoder_convolutional.h     3 Jul 2006 02:14:12 -0000       1.1
@@ -0,0 +1,139 @@
+/* -*- c++ -*- */
+/*
+ * Copyright @ 2006 Michael Dickens
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this library; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef INCLUDED_ENCODER_CONVOLUTIONAL_H
+#define INCLUDED_ENCODER_CONVOLUTIONAL_H
+
+#include <vector>
+#include "encoder.h"
+
+/*!
+ * \brief Encode the incoming streams using a convolutional encoder
+ *
+ * input: streams of char, one stream per input as defined by the
+ *     instantiated code, using only the right-most justified bit as
+ *     the single input bit per input item.
+ *
+ * output: streams of char, one stream per output as defined by the
+ *     instantiated code, using only the right-most justified bit as
+ *     the single output bit per output item.
+ */
+
+class encoder_convolutional : public encoder
+{
+public:
+/*
+ * frame_size_bits: if == 0, then do streaming encoding ("infinite"
+ *     trellis); otherwise this is the frame size in bits to encode
+ *     before terminating the trellis.  This value -does not- include
+ *     any termination bits.
+ *
+ * n_code_inputs:
+ * n_code_outputs:
+ * code_generator: vector of integers (32 bit) representing the code
+ *     to be implemented in octal form.  E.g. "04" in binary is "100",
+ *     which would be "D^2" for code generation.  "06" == 110b == "D^2 + D"
+ *  ==> The vector is listed in order for each input stream, so if there
+ *     are 2 input streams (I1, I2) [specified in "n_code_inputs"]
+ *     and 2 output streams (O1, O2) [specified in "n_code_outputs"],
+ *     then the vector would be the code generator for:
+ *       [I1->O1, I1->O2, I2->O1, I2->O2]
+ *     with each element being the octal representation of the code.
+ *
+ * do_termination: valid only if frame_size_bits != 0, and defines
+ *     whether or not to use trellis termination.  Default is to use
+ *     termination when doing block coding.
+ *
+ * start_memory_state: when starting a new block, the starting memory
+ *     state to begin encoding; there will be a helper function to
+ *     assist in creating this value for a given set of inputs;
+ *     default is the "all zero" state.
+ * 
+ * end_memory_state: when terminating a block, the ending memory
+ *     state to stop encoding; there will be a helper function to
+ *     assist in creating this value for a given set of inputs;
+ *     default is the "all zero" state.
+ */
+
+  encoder_convolutional (int frame_size_bits,
+                        int n_code_inputs,
+                        int n_code_outputs,
+                        std::vector<int> &code_generators,
+                        int start_memory_state = 0,
+                        int end_memory_state = 0,
+                        bool do_termination = true,
+                        bool use_muxed_inputs = false,
+                        bool do_muxed_outputs = false,
+                        bool use_packed_input = false,
+                        bool do_packed_outputs = false);
+
+  virtual ~encoder_convolutional () {};
+
+  virtual size_t compute_n_input_bits (size_t n_output_bits);
+  virtual size_t compute_n_output_bits (size_t n_input_bits);
+  virtual size_t encode (const char** in_buf,
+                        char** out_buf,
+                        size_t n_bits_to_output);
+  virtual size_t encode (const char** in_buf,
+                        size_t n_bits_to_input,
+                        char** out_buf);
+
+private:
+/*
+ * fsm_enc_conv_t: finite state machine for the convolutional encoder;
+ *     output happens all the time, so that's built-in to each state.
+ *
+ * fsm_enc_conv_init: initialize for a new frame / block; this is already
+ *     done at instantiation, so do it only at the end of a block.
+ *
+ * fsm_enc_conv_doing_up: encoding at the start of a block
+ *
+ * fsm_enc_conv_doing_middle: doing encoding inside the trellis
+ *
+ * fsm_enc_conv_doing_term: termination trellis, if requested
+ */
+
+  enum fsm_enc_conv_t {
+    fsm_enc_conv_init, fsm_enc_conv_doing_up,
+    fsm_enc_conv_doing_middle, fsm_enc_conv_doing_term
+  };
+
+  virtual void encode_private (const char** in_buf, char** out_buf);
+  virtual void encode_loop (const char** in_buf, char** out_buf,
+                           size_t* which_counter, size_t how_many);
+  virtual char get_new_input_bit (const char** in_buf, size_t code_input_n);
+  virtual char get_new_input_bit__up (const char** in_buf,
+                                     size_t code_input_n);
+  virtual char get_new_input_bit__middle (const char** in_buf,
+                                         size_t code_input_n);
+  virtual char get_new_input_bit__term (size_t code_input_n);
+  virtual void output_bit (char t_out_bit, char** out_buf,
+                          size_t t_output_stream);
+  virtual void increment_counters (bool while_encoding);
+
+  fsm_enc_conv_t d_fsm_state;
+  bool d_use_muxed_inputs, d_do_muxed_outputs;
+  bool d_use_packed_input, d_do_packed_outputs;
+  bool d_do_streaming, d_do_termination;
+  std::vector<memory_t> d_code_generators;
+  std::vector<memory_t> d_states, d_init_states, d_term_states;
+};
+
+#endif /* INCLUDED_ENCODER_CONVOLUTIONAL_H */

Index: mld/Makefile.am
===================================================================
RCS file: mld/Makefile.am
diff -N mld/Makefile.am
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ mld/Makefile.am     3 Jul 2006 02:14:12 -0000       1.1
@@ -0,0 +1,36 @@
+#
+# Copyright 2005 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+include $(top_srcdir)/Makefile.common
+
+INCLUDES = $(STD_DEFINES_AND_INCLUDES) -I.. -I../..
+
+noinst_LTLIBRARIES = libmld.la
+
+libmld_la_SOURCES =    \
+       mld_timer.cc n2bs.cc
+
+noinst_HEADERS =       \
+       mld_timer.h n2bs.h
+
+MOSTLYCLEANFILES = *.loT *~
+
+CONFIG_CLEAN_FILES = *.in

Index: mld/mld_timer.cc
===================================================================
RCS file: mld/mld_timer.cc
diff -N mld/mld_timer.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ mld/mld_timer.cc    3 Jul 2006 02:14:12 -0000       1.1
@@ -0,0 +1,50 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio.
+ *
+ * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/types.h>
+#include <mld_timer.h>
+
+void start_timer (struct timeval *t_tp)
+{
+  gettimeofday (t_tp, NULL);
+}
+
+u_long end_timer (struct timeval *g_tp)
+{
+  struct timeval t_tp;
+  gettimeofday (&t_tp, NULL);
+
+  u_long retVal = (t_tp.tv_sec - g_tp->tv_sec);
+  u_long df_usec;
+
+  if (t_tp.tv_usec < g_tp->tv_usec) {
+    retVal -= 1;
+    df_usec = 1000000 - (g_tp->tv_usec - t_tp.tv_usec);
+  } else
+    df_usec = t_tp.tv_usec - g_tp->tv_usec;
+
+  retVal *= 1000000;
+  retVal += df_usec;
+  return (retVal);
+}

Index: mld/mld_timer.h
===================================================================
RCS file: mld/mld_timer.h
diff -N mld/mld_timer.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ mld/mld_timer.h     3 Jul 2006 02:14:12 -0000       1.1
@@ -0,0 +1,28 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio.
+ *
+ * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/time.h>
+
+extern void start_timer (struct timeval *t_tp);
+extern u_long end_timer (struct timeval *g_tp);

Index: mld/n2bs.cc
===================================================================
RCS file: mld/n2bs.cc
diff -N mld/n2bs.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ mld/n2bs.cc 3 Jul 2006 02:14:12 -0000       1.1
@@ -0,0 +1,73 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio.
+ *
+ * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <n2bs.h>
+#include <iostream>
+
+const int g_num_bits_per_byte = 8;
+
+std::string n2bs (long long number, size_t digits)
+{
+  if (digits > (sizeof (long long) * g_num_bits_per_byte))
+    digits = sizeof (long long);
+  std::string retVal (digits, '0');
+  if (number != 0)
+    for (int n = --digits; n >= 0; n--) {
+      if (number & 1) {
+       retVal[n] = '1';
+      }
+      number >>= 1;
+    }
+  return (retVal);
+}
+std::string n2bs (char number, size_t digits)
+{
+  if (digits > (sizeof (char) * g_num_bits_per_byte))
+    digits = sizeof (char);
+  return n2bs ((long long) number, digits);
+}
+std::string n2bs (int number, size_t digits)
+{
+  if (digits > (sizeof (int) * g_num_bits_per_byte))
+    digits = sizeof (int);
+  return n2bs ((long long) number, digits);
+}
+std::string n2bs (long number, size_t digits)
+{
+  if (digits > (sizeof (long) * g_num_bits_per_byte))
+    digits = sizeof (long);
+  return n2bs ((long long) number, digits);
+}
+std::string n2bs (size_t number, size_t digits)
+{
+  if (digits > (sizeof (size_t) * g_num_bits_per_byte))
+    digits = sizeof (size_t);
+  return n2bs ((long long) number, digits);
+}
+
+void cout_binary (int number, int digits)
+{
+  while (digits-- > 0)
+    std::cout << ((number >> digits) & 1);
+}

Index: mld/n2bs.h
===================================================================
RCS file: mld/n2bs.h
diff -N mld/n2bs.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ mld/n2bs.h  3 Jul 2006 02:14:12 -0000       1.1
@@ -0,0 +1,32 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio.
+ *
+ * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string>
+
+extern std::string n2bs (char number, size_t digits);
+extern std::string n2bs (int number, size_t digits);
+extern std::string n2bs (long number, size_t digits);
+extern std::string n2bs (size_t number, size_t digits);
+extern std::string n2bs (long long number, size_t digits);
+extern void cout_binary (int number, int digits);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]