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 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 00114 class LLR_calc_unit { 00115 public: 00117 LLR_calc_unit(); 00118 00124 LLR_calc_unit(short int Dint1, short int Dint2, short int Dint3); 00125 00154 void init_llr_tables(short int Dint1 = 12, short int Dint2 = 300, 00155 short int Dint3 = 7); 00156 00158 QLLR to_qllr(double l) const; 00159 00161 QLLRvec to_qllr(const vec &l) const; 00162 00164 QLLRmat to_qllr(const mat &l) const; 00165 00167 double to_double(QLLR l) const; 00168 00170 vec to_double(const QLLRvec &l) const; 00171 00173 mat to_double(const QLLRmat &l) const; 00174 00180 inline QLLR jaclog(QLLR a, QLLR b) const; 00181 // Note: a version of this function taking "double" values as input 00182 // is deliberately omitted, because this is rather slow. 00183 00192 QLLR Boxplus(QLLR a, QLLR b) const; 00193 00199 inline QLLR logexp(QLLR x) const; 00200 00202 ivec get_Dint(); 00203 00205 friend std::ostream &operator<<(std::ostream &os, const LLR_calc_unit &l); 00206 00207 private: 00209 ivec construct_logexp_table(); 00210 00212 ivec logexp_table; 00213 00215 short int Dint1, Dint2, Dint3; 00216 }; 00217 00222 std::ostream &operator<<(std::ostream &os, const LLR_calc_unit &lcu); 00223 00224 00225 // ---------------------------------------------------------------------- 00226 // implementation of some inline functions 00227 // ---------------------------------------------------------------------- 00228 00229 inline double LLR_calc_unit::to_double(QLLR l) const 00230 { 00231 return static_cast<double>(l) / (1<<Dint1); 00232 } 00233 00234 inline QLLR LLR_calc_unit::to_qllr(double l) const 00235 { 00236 double QLLR_MAX_double = to_double(QLLR_MAX); 00237 // Don't abort when overflow occurs, just saturate the QLLR 00238 if (l > QLLR_MAX_double) { 00239 it_info_debug("LLR_calc_unit::to_qllr(): LLR overflow"); 00240 return QLLR_MAX; 00241 } 00242 if (l < -QLLR_MAX_double) { 00243 it_info_debug("LLR_calc_unit::to_qllr(): LLR overflow"); 00244 return -QLLR_MAX; 00245 } 00246 return static_cast<QLLR>(std::floor(0.5 + (1<<Dint1) * l)); 00247 } 00248 00249 00250 inline QLLR LLR_calc_unit::logexp(QLLR x) const 00251 { 00252 it_assert_debug(x >= 0,"LLR_calc_unit::logexp(): Wrong LLR value"); 00253 int ind = x >> Dint3; 00254 if (ind >= Dint2) // outside table 00255 return 0; 00256 00257 it_assert_debug(ind >= 0,"LLR_calc_unit::logexp(): Internal error"); 00258 it_assert_debug(ind < Dint2,"LLR_calc_unit::logexp(): internal error"); 00259 00260 // With interpolation 00261 // int delta=x-(ind<<Dint3); 00262 // return ((delta*logexp_table(ind+1) + ((1<<Dint3)-delta)*logexp_table(ind)) >> Dint3); 00263 00264 // Without interpolation 00265 return logexp_table(ind); 00266 } 00267 00268 00269 inline QLLR LLR_calc_unit::jaclog(QLLR a, QLLR b) const 00270 { 00271 QLLR x, maxab; 00272 00273 if (a > b) { 00274 maxab = a; 00275 x = a - b; 00276 } 00277 else { 00278 maxab = b; 00279 x = b - a; 00280 } 00281 00282 if (maxab >= QLLR_MAX) 00283 return QLLR_MAX; 00284 else 00285 return (maxab + logexp(x)); 00286 } 00287 00288 } 00289 00290 #endif
Generated on Sat Apr 19 10:57:51 2008 for IT++ by Doxygen 1.5.5