IT++ Logo
llr.cpp
Go to the documentation of this file.
00001 
00030 #include <itpp/comm/llr.h>
00031 
00032 
00033 namespace itpp
00034 {
00035 
00036 LLR_calc_unit::LLR_calc_unit()
00037 {
00038   init_llr_tables();
00039 }
00040 
00041 LLR_calc_unit::LLR_calc_unit(short int d1, short int d2, short int d3)
00042 {
00043   init_llr_tables(d1, d2, d3);
00044 }
00045 
00046 ivec LLR_calc_unit::get_Dint()
00047 {
00048   ivec r(3);
00049   r(0) = Dint1;
00050   r(1) = Dint2;
00051   r(2) = Dint3;
00052   return r;
00053 }
00054 
00055 void LLR_calc_unit::init_llr_tables(short int d1, short int d2, short int d3)
00056 {
00057   Dint1 = d1;      // 1<<Dint1 determines how integral LLRs relate to real LLRs (to_double=(1<<Dint)*int_llr)
00058   Dint2 = d2;      // number of entries in table for LLR operations
00059   Dint3 = d3;      // table resolution is 2^(-(Dint1-Dint3))
00060   logexp_table = construct_logexp_table();
00061 }
00062 
00063 ivec LLR_calc_unit::construct_logexp_table()
00064 {
00065   ivec result(Dint2);
00066   for (int i = 0; i < Dint2; i++) {
00067     double x = pow2(static_cast<double>(Dint3 - Dint1)) * i;
00068     result(i) = to_qllr(std::log(1 + std::exp(-x)));
00069   }
00070   it_assert(length(result) == Dint2, "Ldpc_codec::construct_logexp_table()");
00071 
00072   return result;
00073 }
00074 
00075 QLLRvec LLR_calc_unit::to_qllr(const vec &l) const
00076 {
00077   int n = length(l);
00078   ivec result(n);
00079   for (int i = 0; i < n; i++) {
00080     result.set(i, to_qllr(l(i)));
00081   }
00082   return result;
00083 }
00084 
00085 vec LLR_calc_unit::to_double(const QLLRvec &l) const
00086 {
00087   int n = length(l);
00088   vec result(n);
00089   for (int i = 0; i < n; i++) {
00090     result.set(i, to_double(l(i)));
00091   }
00092   return result;
00093 }
00094 
00095 QLLRmat LLR_calc_unit::to_qllr(const mat &l)  const
00096 {
00097   int m = l.rows();
00098   int n = l.cols();
00099   imat result(m, n);
00100   for (int i = 0; i < m; i++) {
00101     for (int j = 0; j < n; j++) {
00102       result.set(i, j, to_qllr(l(i, j)));
00103     }
00104   }
00105   return result;
00106 }
00107 
00108 mat LLR_calc_unit::to_double(const QLLRmat &l) const
00109 {
00110   int m = l.rows();
00111   int n = l.cols();
00112   mat result(m, n);
00113   for (int i = 0; i < m; i++) {
00114     for (int j = 0; j < n; j++) {
00115       result.set(i, j, to_double(l(i, j)));
00116     }
00117   }
00118   return result;
00119 }
00120 
00121 // This function used to be inline, but in my experiments,
00122 // the non-inlined version was actually faster /Martin Senst
00123 QLLR LLR_calc_unit::Boxplus(QLLR a, QLLR b) const
00124 {
00125   QLLR a_abs = (a > 0 ? a : -a);
00126   QLLR b_abs = (b > 0 ? b : -b);
00127   QLLR minabs = (a_abs > b_abs ? b_abs : a_abs);
00128   QLLR term1 = (a > 0 ? (b > 0 ? minabs : -minabs)
00129                     : (b > 0 ? -minabs : minabs));
00130 
00131   if (Dint2 == 0) {  // logmax approximation - avoid looking into empty table
00132     // Don't abort when overflowing, just saturate the QLLR
00133     if (term1 > QLLR_MAX) {
00134       it_info_debug("LLR_calc_unit::Boxplus(): LLR overflow");
00135       return QLLR_MAX;
00136     }
00137     if (term1 < -QLLR_MAX) {
00138       it_info_debug("LLR_calc_unit::Boxplus(): LLR overflow");
00139       return -QLLR_MAX;
00140     }
00141     return term1;
00142   }
00143 
00144   QLLR apb = a + b;
00145   QLLR term2 = logexp((apb > 0 ? apb : -apb));
00146   QLLR amb = a - b;
00147   QLLR term3 = logexp((amb > 0 ? amb : -amb));
00148   QLLR result = term1 + term2 - term3;
00149 
00150   // Don't abort when overflowing, just saturate the QLLR
00151   if (result > QLLR_MAX) {
00152     it_info_debug("LLR_calc_unit::Boxplus() LLR overflow");
00153     return QLLR_MAX;
00154   }
00155   if (result < -QLLR_MAX) {
00156     it_info_debug("LLR_calc_unit::Boxplus() LLR overflow");
00157     return -QLLR_MAX;
00158   }
00159   return result;
00160 }
00161 
00162 std::ostream &operator<<(std::ostream &os, const LLR_calc_unit &lcu)
00163 {
00164   os << "---------- LLR calculation unit -----------------" << std::endl;
00165   os << "LLR_calc_unit table properties:" << std::endl;
00166   os << "The granularity in the LLR representation is "
00167   << pow2(static_cast<double>(-lcu.Dint1)) << std::endl;
00168   os << "The LLR scale factor is " << (1 << lcu.Dint1) << std::endl;
00169   os << "The largest LLR that can be represented is "
00170   << lcu.to_double(QLLR_MAX) << std::endl;
00171   os << "The table resolution is "
00172   << pow2(static_cast<double>(lcu.Dint3 - lcu.Dint1)) << std::endl;
00173   os << "The number of entries in the table is " << lcu.Dint2 << std::endl;
00174   os << "The tables truncates at the LLR value "
00175   << pow2(static_cast<double>(lcu.Dint3 - lcu.Dint1)) * lcu.Dint2
00176   << std::endl;
00177   os << "-------------------------------------------------" << std::endl;
00178   return os;
00179 }
00180 
00181 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
SourceForge Logo

Generated on Wed Jul 27 2011 16:27:05 for IT++ by Doxygen 1.7.4