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