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