Houston, we have a trunk.
[debian/gnuradio] / gr-error-correcting-codes / src / lib / libecc / code_metrics.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <code_metrics.h>
28 #include <iostream>
29 #include <math.h>
30 #include <assert.h>
31
32 code_metric_ff::code_metric_ff
33 (pdf_fcn_t pdf_fcn_0_bit,
34  pdf_fcn_t pdf_fcn_1_bit,
35  size_t n_samples,
36  pdf_fcn_io_t min_sample,
37  pdf_fcn_io_t max_sample)
38 {
39   if (n_samples < 2) {
40     fprintf (stderr, "code_metric_f32:: n_samples "
41              "must be at least 2.\n");
42     assert (0);
43   }
44   if (min_sample >= max_sample) {
45     fprintf (stderr, "code_metric_f32:: min_sample must be "
46              "less than max_sample.\n");
47     assert (0);
48   }
49   if (! pdf_fcn_0_bit) {
50     fprintf (stderr, "code_metric_f32:: pdf_fcn_0_bit must be "
51              "a non-null pointer to function.\n");
52     assert (0);
53   }
54   if (! pdf_fcn_1_bit) {
55     fprintf (stderr, "code_metric_f32:: pdf_fcn_0_bit must be "
56              "a non-null pointer to function.\n");
57     assert (0);
58   }
59
60   d_n_samples = n_samples;
61   d_max_sample = max_sample;
62   d_min_sample = min_sample;
63   d_delta = (max_sample - min_sample) / (n_samples - 1);
64   d_pdf_fcn_0_bit = pdf_fcn_0_bit;
65   d_pdf_fcn_1_bit = pdf_fcn_1_bit;
66   d_metric_table_0_bit.assign (n_samples, 0);
67   d_metric_table_1_bit.assign (n_samples, 0);
68
69   pdf_fcn_io_t l_val = min_sample;
70   for (size_t m = 0; m < n_samples; m++) {
71     d_metric_table_0_bit[m] = logf ((*pdf_fcn_0_bit)(l_val));
72     d_metric_table_1_bit[m] = logf ((*pdf_fcn_1_bit)(l_val));
73     l_val += d_delta;
74   }
75 }
76
77 void code_metric_ff::lookup
78 (pdf_fcn_io_t sym,
79  void* bit_0,
80  void* bit_1)
81 {
82   metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
83   metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
84
85   if (sym <= d_min_sample) {
86     *l_bit_0 = d_metric_table_0_bit[0];
87     *l_bit_1 = d_metric_table_1_bit[0];
88     return;
89   }
90   if (sym >= d_max_sample) {
91     *l_bit_0 = d_metric_table_0_bit.back ();
92     *l_bit_1 = d_metric_table_1_bit.back ();
93     return;
94   }
95
96   size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta);
97   *l_bit_0 = d_metric_table_0_bit[l_ndx];
98   *l_bit_1 = d_metric_table_1_bit[l_ndx];
99 }
100
101 void code_metric_ff::convert
102 (size_t n_syms,
103  pdf_fcn_io_t* sym,
104  void* bit_0,
105  void* bit_1)
106 {
107   metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
108   metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
109
110   for (size_t m = n_syms; m > 0; m--)
111     lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
112 }
113
114 code_metric_fl::code_metric_fl
115 (pdf_fcn_t pdf_fcn_0_bit,
116  pdf_fcn_t pdf_fcn_1_bit,
117  size_t n_samples,
118  pdf_fcn_io_t min_sample,
119  pdf_fcn_io_t max_sample,
120  int sample_precision)
121 {
122   if (n_samples < 2) {
123     fprintf (stderr, "code_metric_fl:: n_samples "
124              "must be at least 2.\n");
125     assert (0);
126   }
127   if (min_sample >= max_sample) {
128     fprintf (stderr, "code_metric_fl:: min_sample must be "
129              "less than max_sample.\n");
130     assert (0);
131   }
132   if (! pdf_fcn_0_bit) {
133     fprintf (stderr, "code_metric_fl:: pdf_fcn_0_bit must be "
134              "a non-null pointer to function.\n");
135     assert (0);
136   }
137   if (! pdf_fcn_1_bit) {
138     fprintf (stderr, "code_metric_fl:: pdf_fcn_0_bit must be "
139              "a non-null pointer to function.\n");
140     assert (0);
141   }
142   if (sample_precision < 16 || sample_precision > 32) {
143     fprintf (stderr, "code_metric_fl:: sample_precision must be "
144              "between 16 and 32 for this class.\n");
145     assert (0);
146   }
147
148   d_sample_precision = sample_precision;
149   d_n_samples = n_samples;
150   d_max_sample = max_sample;
151   d_min_sample = min_sample;
152   d_delta = (max_sample - min_sample) / (n_samples - 1);
153   d_pdf_fcn_0_bit = pdf_fcn_0_bit;
154   d_pdf_fcn_1_bit = pdf_fcn_1_bit;
155   d_metric_table_0_bit.assign (n_samples, 0);
156   d_metric_table_1_bit.assign (n_samples, 0);
157
158   // get the scale factor for converting from float to sample_precision
159   // maps:
160   //    logf (pdf_fcn_0_bit->eval (d_min_sample))  ->  l_min_map
161   //    logf (pdf_fcn_0_bit->eval (d_max_sample))  ->  l_max_map
162
163   metric_t l_min_map = - (1 << (sample_precision - 1));
164
165   pdf_fcn_io_t l_min_log_val_0 = logf ((*pdf_fcn_0_bit)(d_min_sample));
166   pdf_fcn_io_t l_max_log_val_0 = logf ((*pdf_fcn_0_bit)(d_max_sample));
167   pdf_fcn_io_t l_slope_0 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
168                             (l_max_log_val_0 - l_min_log_val_0));
169   pdf_fcn_io_t l_min_log_val_1 = logf ((*pdf_fcn_1_bit)(d_min_sample));
170   pdf_fcn_io_t l_max_log_val_1 = logf ((*pdf_fcn_1_bit)(d_max_sample));
171   pdf_fcn_io_t l_slope_1 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
172                             (l_max_log_val_1 - l_min_log_val_1));
173
174   pdf_fcn_io_t l_val = d_min_sample;
175   for (size_t m = 0; m < d_n_samples; m++) {
176     d_metric_table_0_bit[m] =
177       (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
178                          (l_slope_0 * (logf ((*pdf_fcn_0_bit)(l_val)) -
179                                        l_min_log_val_0)));
180     d_metric_table_1_bit[m] =
181       (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
182                          (l_slope_1 * (logf ((*pdf_fcn_1_bit)(l_val)) -
183                                        l_min_log_val_1)));
184     l_val += d_delta;
185   }
186 }
187
188 void code_metric_fl::lookup
189 (pdf_fcn_io_t sym,
190  void* bit_0,
191  void* bit_1)
192 {
193   metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
194   metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
195
196   if (sym <= d_min_sample) {
197     *l_bit_0 = d_metric_table_0_bit[0];
198     *l_bit_1 = d_metric_table_1_bit[0];
199     return;
200   }
201   if (sym >= d_max_sample) {
202     *l_bit_0 = d_metric_table_0_bit.back ();
203     *l_bit_1 = d_metric_table_1_bit.back ();
204     return;
205   }
206
207   size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta);
208   *l_bit_0 = d_metric_table_0_bit[l_ndx];
209   *l_bit_1 = d_metric_table_1_bit[l_ndx];
210 }
211
212 void code_metric_fl::convert
213 (size_t n_syms,
214  pdf_fcn_io_t* sym,
215  void* bit_0,
216  void* bit_1)
217 {
218   metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
219   metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
220
221   for (size_t m = n_syms; m > 0; m--)
222     lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
223 }
224
225 code_metric_fs::code_metric_fs
226 (pdf_fcn_t pdf_fcn_0_bit,
227  pdf_fcn_t pdf_fcn_1_bit,
228  size_t n_samples,
229  pdf_fcn_io_t min_sample,
230  pdf_fcn_io_t max_sample,
231  int sample_precision)
232 {
233   if (n_samples < 2) {
234     fprintf (stderr, "code_metric_fs:: n_samples "
235              "must be at least 2.\n");
236     assert (0);
237   }
238   if (min_sample >= max_sample) {
239     fprintf (stderr, "code_metric_fs:: min_sample must be "
240              "less than max_sample.\n");
241     assert (0);
242   }
243   if (! pdf_fcn_0_bit) {
244     fprintf (stderr, "code_metric_fs:: pdf_fcn_0_bit must be "
245              "a non-null pointer to function.\n");
246     assert (0);
247   }
248   if (! pdf_fcn_1_bit) {
249     fprintf (stderr, "code_metric_fs:: pdf_fcn_0_bit must be "
250              "a non-null pointer to function.\n");
251     assert (0);
252   }
253   if (sample_precision < 9 || sample_precision > 16) {
254     fprintf (stderr, "code_metric_fs:: sample_precision must be "
255              "between 9 and 16 for this class.\n");
256     assert (0);
257   }
258
259   d_sample_precision = sample_precision;
260   d_n_samples = n_samples;
261   d_max_sample = max_sample;
262   d_min_sample = min_sample;
263   d_delta = (max_sample - min_sample) / (n_samples - 1);
264   d_pdf_fcn_0_bit = pdf_fcn_0_bit;
265   d_pdf_fcn_1_bit = pdf_fcn_1_bit;
266   d_metric_table_0_bit.assign (n_samples, 0);
267   d_metric_table_1_bit.assign (n_samples, 0);
268
269   // get the scale factor for converting from float to sample_precision
270   // maps:
271   //    logf (pdf_fcn_0_bit->eval (d_min_sample))  ->  l_min_map
272   //    logf (pdf_fcn_0_bit->eval (d_max_sample))  ->  l_max_map
273
274   metric_t l_min_map = - (1 << (sample_precision - 1));
275
276   pdf_fcn_io_t l_min_log_val_0 = logf ((*pdf_fcn_0_bit)(d_min_sample));
277   pdf_fcn_io_t l_max_log_val_0 = logf ((*pdf_fcn_0_bit)(d_max_sample));
278   pdf_fcn_io_t l_slope_0 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
279                             (l_max_log_val_0 - l_min_log_val_0));
280   pdf_fcn_io_t l_min_log_val_1 = logf ((*pdf_fcn_1_bit)(d_min_sample));
281   pdf_fcn_io_t l_max_log_val_1 = logf ((*pdf_fcn_1_bit)(d_max_sample));
282   pdf_fcn_io_t l_slope_1 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
283                             (l_max_log_val_1 - l_min_log_val_1));
284
285   pdf_fcn_io_t l_val = d_min_sample;
286   for (size_t m = 0; m < d_n_samples; m++) {
287     d_metric_table_0_bit[m] =
288       (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
289                          (l_slope_0 * (logf ((*pdf_fcn_0_bit)(l_val)) -
290                                        l_min_log_val_0)));
291     d_metric_table_1_bit[m] =
292       (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
293                          (l_slope_1 * (logf ((*pdf_fcn_1_bit)(l_val)) -
294                                        l_min_log_val_1)));
295     l_val += d_delta;
296   }
297 }
298
299 void code_metric_fs::lookup
300 (pdf_fcn_io_t sym,
301  void* bit_0,
302  void* bit_1)
303 {
304   metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
305   metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
306
307   if (sym <= d_min_sample) {
308     *l_bit_0 = d_metric_table_0_bit[0];
309     *l_bit_1 = d_metric_table_1_bit[0];
310     return;
311   }
312   if (sym >= d_max_sample) {
313     *l_bit_0 = d_metric_table_0_bit.back ();
314     *l_bit_1 = d_metric_table_1_bit.back ();
315     return;
316   }
317
318   size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta);
319   *l_bit_0 = d_metric_table_0_bit[l_ndx];
320   *l_bit_1 = d_metric_table_1_bit[l_ndx];
321 }
322
323 void code_metric_fs::convert
324 (size_t n_syms,
325  pdf_fcn_io_t* sym,
326  void* bit_0,
327  void* bit_1)
328 {
329   metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
330   metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
331
332   for (size_t m = n_syms; m > 0; m--)
333     lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
334 }
335
336 code_metric_fb::code_metric_fb
337 (pdf_fcn_t pdf_fcn_0_bit,
338  pdf_fcn_t pdf_fcn_1_bit,
339  size_t n_samples,
340  pdf_fcn_io_t min_sample,
341  pdf_fcn_io_t max_sample,
342  int sample_precision)
343 {
344   if (n_samples < 2) {
345     fprintf (stderr, "code_metric_fb:: n_samples "
346              "must be at least 2.\n");
347     assert (0);
348   }
349   if (min_sample >= max_sample) {
350     fprintf (stderr, "code_metric_fb:: min_sample must be "
351              "less than max_sample.\n");
352     assert (0);
353   }
354   if (! pdf_fcn_0_bit) {
355     fprintf (stderr, "code_metric_fb:: pdf_fcn_0_bit must be "
356              "a non-null pointer to function.\n");
357     assert (0);
358   }
359   if (! pdf_fcn_1_bit) {
360     fprintf (stderr, "code_metric_fb:: pdf_fcn_0_bit must be "
361              "a non-null pointer to function.\n");
362     assert (0);
363   }
364   if (sample_precision < 1 || sample_precision > 8) {
365     fprintf (stderr, "code_metric_fb:: sample_precision must be "
366              "between 1 and 8 for this class.\n");
367     assert (0);
368   }
369
370   d_sample_precision = sample_precision;
371   d_n_samples = n_samples;
372   d_max_sample = max_sample;
373   d_min_sample = min_sample;
374   d_delta = (max_sample - min_sample) / (n_samples - 1);
375   d_pdf_fcn_0_bit = pdf_fcn_0_bit;
376   d_pdf_fcn_1_bit = pdf_fcn_1_bit;
377   d_metric_table_0_bit.assign (n_samples, 0);
378   d_metric_table_1_bit.assign (n_samples, 0);
379
380   // get the scale factor for converting from float to sample_precision
381   // maps:
382   //    logf (pdf_fcn_0_bit->eval (d_min_sample))  ->  l_min_map
383   //    logf (pdf_fcn_0_bit->eval (d_max_sample))  ->  l_max_map
384
385   metric_t l_min_map = - (1 << (sample_precision - 1));
386
387   pdf_fcn_io_t l_min_log_val_0 = logf ((*pdf_fcn_0_bit)(d_min_sample));
388   pdf_fcn_io_t l_max_log_val_0 = logf ((*pdf_fcn_0_bit)(d_max_sample));
389   pdf_fcn_io_t l_slope_0 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
390                             (l_max_log_val_0 - l_min_log_val_0));
391   pdf_fcn_io_t l_min_log_val_1 = logf ((*pdf_fcn_1_bit)(d_min_sample));
392   pdf_fcn_io_t l_max_log_val_1 = logf ((*pdf_fcn_1_bit)(d_max_sample));
393   pdf_fcn_io_t l_slope_1 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
394                             (l_max_log_val_1 - l_min_log_val_1));
395
396   pdf_fcn_io_t l_val = d_min_sample;
397   for (size_t m = 0; m < d_n_samples; m++) {
398     d_metric_table_0_bit[m] =
399       (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
400                          (l_slope_0 * (logf ((*pdf_fcn_0_bit)(l_val)) -
401                                        l_min_log_val_0)));
402     d_metric_table_1_bit[m] =
403       (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
404                          (l_slope_1 * (logf ((*pdf_fcn_1_bit)(l_val)) -
405                                        l_min_log_val_1)));
406     l_val += d_delta;
407   }
408 }
409
410 void code_metric_fb::lookup
411 (pdf_fcn_io_t sym,
412  void* bit_0,
413  void* bit_1)
414 {
415   metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
416   metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
417
418   if (sym <= d_min_sample) {
419     *l_bit_0 = d_metric_table_0_bit[0];
420     *l_bit_1 = d_metric_table_1_bit[0];
421     return;
422   }
423   if (sym >= d_max_sample) {
424     *l_bit_0 = d_metric_table_0_bit.back ();
425     *l_bit_1 = d_metric_table_1_bit.back ();
426     return;
427   }
428
429   size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta);
430   *l_bit_0 = d_metric_table_0_bit[l_ndx];
431   *l_bit_1 = d_metric_table_1_bit[l_ndx];
432 }
433
434 void code_metric_fb::convert
435 (size_t n_syms,
436  pdf_fcn_io_t* sym,
437  void* bit_0,
438  void* bit_1)
439 {
440   metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
441   metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
442
443   for (size_t m = n_syms; m > 0; m--)
444     lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
445 }