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 00115 class LLR_calc_unit 00116 { 00117 public: 00119 LLR_calc_unit(); 00120 00126 LLR_calc_unit(short int Dint1, short int Dint2, short int Dint3); 00127 00156 void init_llr_tables(short int Dint1 = 12, short int Dint2 = 300, 00157 short int Dint3 = 7); 00158 00160 QLLR to_qllr(double l) const; 00161 00163 QLLRvec to_qllr(const vec &l) const; 00164 00166 QLLRmat to_qllr(const mat &l) const; 00167 00169 double to_double(QLLR l) const; 00170 00172 vec to_double(const QLLRvec &l) const; 00173 00175 mat to_double(const QLLRmat &l) const; 00176 00182 inline QLLR jaclog(QLLR a, QLLR b) const; 00183 // Note: a version of this function taking "double" values as input 00184 // is deliberately omitted, because this is rather slow. 00185 00194 QLLR Boxplus(QLLR a, QLLR b) const; 00195 00201 inline QLLR logexp(QLLR x) const; 00202 00204 ivec get_Dint(); 00205 00207 friend std::ostream &operator<<(std::ostream &os, const LLR_calc_unit &l); 00208 00209 private: 00211 ivec construct_logexp_table(); 00212 00214 ivec logexp_table; 00215 00217 short int Dint1, Dint2, Dint3; 00218 }; 00219 00224 std::ostream &operator<<(std::ostream &os, const LLR_calc_unit &lcu); 00225 00226 00227 // ---------------------------------------------------------------------- 00228 // implementation of some inline functions 00229 // ---------------------------------------------------------------------- 00230 00231 inline double LLR_calc_unit::to_double(QLLR l) const 00232 { 00233 return static_cast<double>(l) / (1 << Dint1); 00234 } 00235 00236 inline QLLR LLR_calc_unit::to_qllr(double l) const 00237 { 00238 double QLLR_MAX_double = to_double(QLLR_MAX); 00239 // Don't abort when overflow occurs, just saturate the QLLR 00240 if (l > QLLR_MAX_double) { 00241 it_info_debug("LLR_calc_unit::to_qllr(): LLR overflow"); 00242 return QLLR_MAX; 00243 } 00244 if (l < -QLLR_MAX_double) { 00245 it_info_debug("LLR_calc_unit::to_qllr(): LLR overflow"); 00246 return -QLLR_MAX; 00247 } 00248 return static_cast<QLLR>(std::floor(0.5 + (1 << Dint1) * l)); 00249 } 00250 00251 00252 inline QLLR LLR_calc_unit::logexp(QLLR x) const 00253 { 00254 it_assert_debug(x >= 0, "LLR_calc_unit::logexp(): Wrong LLR value"); 00255 int ind = x >> Dint3; 00256 if (ind >= Dint2) // outside table 00257 return 0; 00258 00259 it_assert_debug(ind >= 0, "LLR_calc_unit::logexp(): Internal error"); 00260 it_assert_debug(ind < Dint2, "LLR_calc_unit::logexp(): internal error"); 00261 00262 // With interpolation 00263 // int delta=x-(ind<<Dint3); 00264 // return ((delta*logexp_table(ind+1) + ((1<<Dint3)-delta)*logexp_table(ind)) >> Dint3); 00265 00266 // Without interpolation 00267 return logexp_table(ind); 00268 } 00269 00270 00271 inline QLLR LLR_calc_unit::jaclog(QLLR a, QLLR b) const 00272 { 00273 QLLR x, maxab; 00274 00275 if (a > b) { 00276 maxab = a; 00277 x = a - b; 00278 } 00279 else { 00280 maxab = b; 00281 x = b - a; 00282 } 00283 00284 if (maxab >= QLLR_MAX) 00285 return QLLR_MAX; 00286 else 00287 return (maxab + logexp(x)); 00288 } 00289 00290 } 00291 00292 #endif
Generated on Tue Dec 6 2011 16:51:54 for IT++ by Doxygen 1.7.4