IT++ Logo

llr.cpp

Go to the documentation of this file.
00001 
00031 #include <itpp/comm/llr.h>
00032 
00033 
00034 namespace itpp {
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     int n=length(l);
00077     ivec result(n);
00078     for (int i=0; i<n; i++) {
00079       result.set(i,to_qllr(l(i)));
00080     }
00081     return result;
00082   }
00083 
00084   vec LLR_calc_unit::to_double(const QLLRvec &l) const {
00085     int n=length(l);
00086     vec result(n);
00087     for (int i=0; i<n; i++) {
00088       result.set(i,to_double(l(i)));
00089     }
00090     return result;
00091   }
00092 
00093   QLLRmat LLR_calc_unit::to_qllr(const mat &l)  const {
00094     int m=l.rows();
00095     int n=l.cols();
00096     imat result(m,n);
00097     for (int i=0; i<m; i++) {
00098       for (int j=0; j<n; j++) {
00099         result.set(i,j,to_qllr(l(i,j)));
00100       }
00101     }
00102     return result;
00103   }
00104 
00105   mat LLR_calc_unit::to_double(const QLLRmat &l) const {
00106     int m=l.rows();
00107     int n=l.cols();
00108     mat result(m,n);
00109     for (int i=0; i<m; i++) {
00110       for (int j=0; j<n; j++) {
00111         result.set(i,j,to_double(l(i,j)));
00112       }
00113     }
00114     return result;
00115   }
00116 
00117   // This function used to be inline, but in my experiments,
00118   // the non-inlined version was actually faster /Martin Senst
00119   QLLR LLR_calc_unit::Boxplus(QLLR a, QLLR b) const
00120   {
00121     QLLR a_abs = (a > 0 ? a : -a);
00122     QLLR b_abs = (b > 0 ? b : -b);
00123     QLLR minabs = (a_abs > b_abs ? b_abs : a_abs);
00124     QLLR term1 = (a > 0 ? (b > 0 ? minabs : -minabs)
00125                         : (b > 0 ? -minabs : minabs));
00126 
00127     if (Dint2 == 0) {  // logmax approximation - avoid looking into empty table
00128       // Don't abort when overflowing, just saturate the QLLR
00129       if (term1 > QLLR_MAX) {
00130         it_info_debug("LLR_calc_unit::Boxplus(): LLR overflow");
00131         return QLLR_MAX;
00132       }
00133       if (term1 < -QLLR_MAX) {
00134         it_info_debug("LLR_calc_unit::Boxplus(): LLR overflow");
00135         return -QLLR_MAX;
00136       }
00137       return term1;
00138     }
00139 
00140     QLLR apb = a + b;
00141     QLLR term2 = logexp((apb > 0 ? apb : -apb));
00142     QLLR amb = a - b;
00143     QLLR term3 = logexp((amb > 0 ? amb : -amb));
00144     QLLR result = term1 + term2 - term3;
00145 
00146     // Don't abort when overflowing, just saturate the QLLR
00147     if (result > QLLR_MAX) {
00148       it_info_debug("LLR_calc_unit::Boxplus() LLR overflow");
00149       return QLLR_MAX;
00150     }
00151     if (result < -QLLR_MAX) {
00152       it_info_debug("LLR_calc_unit::Boxplus() LLR overflow");
00153       return -QLLR_MAX;
00154     }
00155     return result;
00156   }
00157 
00158   std::ostream &operator<<(std::ostream &os, const LLR_calc_unit &lcu)
00159   {
00160     os << "---------- LLR calculation unit -----------------" << std::endl;
00161     os << "LLR_calc_unit table properties:" << std::endl;
00162     os << "The granularity in the LLR representation is "
00163        << pow2(static_cast<double>(-lcu.Dint1)) << std::endl;
00164     os << "The LLR scale factor is " << (1 << lcu.Dint1) << std::endl;
00165     os << "The largest LLR that can be represented is "
00166        << lcu.to_double(QLLR_MAX) << std::endl;
00167     os << "The table resolution is "
00168        << pow2(static_cast<double>(lcu.Dint3 - lcu.Dint1)) << std::endl;
00169     os << "The number of entries in the table is " << lcu.Dint2 << std::endl;
00170     os << "The tables truncates at the LLR value "
00171        << pow2(static_cast<double>(lcu.Dint3 - lcu.Dint1)) * lcu.Dint2
00172        << std::endl;
00173     os << "-------------------------------------------------" << std::endl;
00174     return os;
00175   }
00176 
00177 }
SourceForge Logo

Generated on Sat Apr 19 11:01:26 2008 for IT++ by Doxygen 1.5.5