00001 00029 #ifndef LLR_H 00030 #define LLR_H 00031 00032 #include <limits> 00033 #include <itpp/base/vec.h> 00034 #include <itpp/base/mat.h> 00035 #include <itpp/base/specmat.h> 00036 #include <itpp/base/matfunc.h> 00037 #include <limits> 00038 00039 namespace itpp 00040 { 00041 00045 typedef signed int QLLR; 00046 00050 typedef Vec<QLLR> QLLRvec; 00051 00055 typedef Mat<QLLR> QLLRmat; 00056 00060 const QLLR QLLR_MAX = (std::numeric_limits<QLLR>::max() >> 4); 00061 // added some margin to make sure the sum of two LLR is still permissible 00062 00123 class LLR_calc_unit 00124 { 00125 public: 00127 LLR_calc_unit(); 00128 00134 LLR_calc_unit(short int Dint1, short int Dint2, short int Dint3); 00135 00164 void init_llr_tables(short int Dint1 = 12, short int Dint2 = 300, 00165 short int Dint3 = 7); 00166 00168 QLLR to_qllr(double l) const; 00169 00171 QLLRvec to_qllr(const vec &l) const; 00172 00174 QLLRmat to_qllr(const mat &l) const; 00175 00177 double to_double(QLLR l) const; 00178 00180 vec to_double(const QLLRvec &l) const; 00181 00183 mat to_double(const QLLRmat &l) const; 00184 00190 inline QLLR jaclog(QLLR a, QLLR b) const; 00191 // Note: a version of this function taking "double" values as input 00192 // is deliberately omitted, because this is rather slow. 00193 00202 QLLR Boxplus(QLLR a, QLLR b) const; 00203 00209 inline QLLR logexp(QLLR x) const; 00210 00212 ivec get_Dint(); 00213 00215 friend std::ostream &operator<<(std::ostream &os, const LLR_calc_unit &l); 00216 00217 private: 00219 ivec construct_logexp_table(); 00220 00222 ivec logexp_table; 00223 00225 short int Dint1, Dint2, Dint3; 00226 }; 00227 00232 std::ostream &operator<<(std::ostream &os, const LLR_calc_unit &lcu); 00233 00234 00235 // ---------------------------------------------------------------------- 00236 // implementation of some inline functions 00237 // ---------------------------------------------------------------------- 00238 00239 inline double LLR_calc_unit::to_double(QLLR l) const 00240 { 00241 return static_cast<double>(l) / (1 << Dint1); 00242 } 00243 00244 inline QLLR LLR_calc_unit::to_qllr(double l) const 00245 { 00246 double QLLR_MAX_double = to_double(QLLR_MAX); 00247 // Don't abort when overflow occurs, just saturate the QLLR 00248 if (l > QLLR_MAX_double) { 00249 it_info_debug("LLR_calc_unit::to_qllr(): LLR overflow"); 00250 return QLLR_MAX; 00251 } 00252 if (l < -QLLR_MAX_double) { 00253 it_info_debug("LLR_calc_unit::to_qllr(): LLR overflow"); 00254 return -QLLR_MAX; 00255 } 00256 return static_cast<QLLR>(std::floor(0.5 + (1 << Dint1) * l)); 00257 } 00258 00259 00260 inline QLLR LLR_calc_unit::logexp(QLLR x) const 00261 { 00262 it_assert_debug(x >= 0, "LLR_calc_unit::logexp(): Wrong LLR value"); 00263 int ind = x >> Dint3; 00264 if (ind >= Dint2) // outside table 00265 return 0; 00266 00267 it_assert_debug(ind >= 0, "LLR_calc_unit::logexp(): Internal error"); 00268 it_assert_debug(ind < Dint2, "LLR_calc_unit::logexp(): internal error"); 00269 00270 // With interpolation 00271 // int delta=x-(ind<<Dint3); 00272 // return ((delta*logexp_table(ind+1) + ((1<<Dint3)-delta)*logexp_table(ind)) >> Dint3); 00273 00274 // Without interpolation 00275 return logexp_table(ind); 00276 } 00277 00278 00279 inline QLLR LLR_calc_unit::jaclog(QLLR a, QLLR b) const 00280 { 00281 QLLR x, maxab; 00282 00283 if (a > b) { 00284 maxab = a; 00285 x = a - b; 00286 } 00287 else { 00288 maxab = b; 00289 x = b - a; 00290 } 00291 00292 if (maxab >= QLLR_MAX) 00293 return QLLR_MAX; 00294 else 00295 return (maxab + logexp(x)); 00296 } 00297 00298 } 00299 00300 #endif
Generated on Wed Jul 27 2011 16:27:05 for IT++ by Doxygen 1.7.4