33 #include <itpp/itexports.h>
93 void set_map_metric(
const std::string &in_MAP_metric);
98 void set_precoder_generator(
const itpp::bvec &in_prec_gen);
99 void set_precoder_generator(
const int &in_prec_gen,
const int &constraint_length);
104 void set_generators(
const itpp::bmat &in_gen);
105 void set_generators(
const itpp::ivec &in_gen,
const int &constraint_length);
111 void set_tail(
const bool &in_tail);
113 void set_viterbi_win_len(
const int &win_len);
115 void set_sova_scaling_factor(
const double &scaling_factor);
117 void set_sova_threshold(
const double &threshold);
119 void set_viterbi_scaling_factors(
const double &matching_scaling_factor,
120 const double &nonmatching_scaling_factor
123 void set_viterbi_hard_output_flag(
const bool &flag);
126 void set_noise(
const double &in_sigma2);
130 void set_impulse_response(
const itpp::vec &h);
134 void set_impulse_response(
const itpp::mat &H);
138 void set_impulse_response(
const itpp::cvec &h);
161 void set_impulse_response(
const itpp::cmat &cH);
167 void set_scrambler_pattern(
const itpp::vec &phi);
168 void set_scrambler_pattern(
const itpp::bvec &phi);
175 void set_mud_method(
const std::string &method);
182 void set_constellation(
const int &in_nb_bits_symb,
183 const itpp::cvec &in_constellation,
186 void set_constellation(
const int &in_nb_bits_symb,
187 const itpp::cvec &in_constellation,
188 const itpp::ivec &in_int_constellation
193 void set_st_block_code(
const int &Q,
209 void set_demapper_method(
const std::string &method);
211 void rsc(itpp::vec &extrinsic_coded,
212 itpp::vec &extrinsic_data,
213 const itpp::vec &intrinsic_coded,
214 const itpp::vec &apriori_data
217 void rsc(itpp::vec &extrinsic_coded,
218 itpp::vec &extrinsic_data,
219 const itpp::vec &intrinsic_coded,
220 const itpp::vec &apriori_data,
224 void nsc(itpp::vec &extrinsic_coded,
225 itpp::vec &extrinsic_data,
226 const itpp::vec &intrinsic_coded,
227 const itpp::vec &apriori_data
230 void nsc(itpp::vec &extrinsic_coded,
231 itpp::vec &extrinsic_data,
232 const itpp::vec &intrinsic_coded,
233 const itpp::vec &apriori_data,
240 void equalizer(itpp::vec &extrinsic_data,
241 const itpp::vec &rec_sig,
242 const itpp::vec &apriori_data
248 void equalizer(itpp::vec &extrinsic_data,
249 const itpp::vec &rec_sig,
250 const itpp::vec &apriori_data,
254 void descrambler(itpp::vec &extrinsic_coded,
255 itpp::vec &extrinsic_data,
256 const itpp::vec &intrinsic_coded,
257 const itpp::vec &apriori_data
260 void mud(itpp::mat &extrinsic_data,
261 const itpp::vec &rec_sig,
262 const itpp::mat &apriori_data
265 void demapper(itpp::vec &extrinsic_data,
266 const itpp::cvec &rec_sig,
267 const itpp::vec &apriori_data
270 void demapper(itpp::vec &extrinsic_data,
271 const itpp::cmat &rec_sig,
272 const itpp::vec &apriori_data
275 static double threshold(
const double &x,
const double &value);
276 static itpp::vec threshold(
const itpp::vec &in,
const double &value);
277 static itpp::mat threshold(
const itpp::mat &in,
const double &value);
280 void rsc_logMAP(itpp::vec &extrinsic_coded, itpp::vec &extrinsic_data,
281 const itpp::vec &intrinsic_coded,
const itpp::vec &apriori_data);
283 void rsc_maxlogMAP(itpp::vec &extrinsic_coded, itpp::vec &extrinsic_data,
284 const itpp::vec &intrinsic_coded,
const itpp::vec &apriori_data);
286 void rsc_sova(itpp::vec &extrinsic_data,
287 const itpp::vec &intrinsic_coded,
288 const itpp::vec &apriori_data,
292 void rsc_viterbi(itpp::vec &extrinsic_coded,
293 itpp::vec &extrinsic_data,
294 const itpp::vec &intrinsic_coded,
295 const itpp::vec &apriori_data,
299 void nsc_logMAP(itpp::vec &extrinsic_coded, itpp::vec &extrinsic_data,
300 const itpp::vec &intrinsic_coded,
const itpp::vec &apriori_data);
302 void nsc_maxlogMAP(itpp::vec &extrinsic_coded, itpp::vec &extrinsic_data,
303 const itpp::vec &intrinsic_coded,
const itpp::vec &apriori_data);
305 void equalizer_logMAP(itpp::vec &extrinsic_data,
const itpp::vec &rec_sig,
306 const itpp::vec &apriori_data);
308 void equalizer_maxlogMAP(itpp::vec &extrinsic_data,
const itpp::vec &rec_sig,
309 const itpp::vec &apriori_data);
311 void mud_maxlogMAP(itpp::mat &extrinsic_data,
const itpp::vec &rec_sig,
312 const itpp::mat &apriori_data);
314 void mud_maxlogTMAP(itpp::mat &extrinsic_data,
const itpp::vec &rec_sig,
315 const itpp::mat &apriori_data,
const double &threshold=-5);
317 void GCD(itpp::mat &extrinsic_data,
const itpp::vec &rec_sig,
318 const itpp::mat &apriori_data);
320 void sGCD(itpp::mat &extrinsic_data,
const itpp::vec &rec_sig,
321 const itpp::mat &apriori_data);
323 void Hassibi_maxlogMAP(itpp::vec &extrinsic_data,
const itpp::cmat &rec_sig,
324 const itpp::vec &apriori_data);
326 void GA(itpp::vec &extrinsic_data,
const itpp::cmat &rec_sig,
327 const itpp::vec &apriori_data);
329 void sGA(itpp::vec &extrinsic_data,
const itpp::cmat &rec_sig,
330 const itpp::vec &apriori_data);
332 void mmsePIC(itpp::vec &extrinsic_data,
const itpp::cmat &rec_sig,
333 const itpp::vec &apriori_data);
335 void zfPIC(itpp::vec &extrinsic_data,
const itpp::cmat &rec_sig,
336 const itpp::vec &apriori_data);
338 void Alamouti_maxlogMAP(itpp::vec &extrinsic_data,
const itpp::cmat &rec_sig,
339 const itpp::vec &apriori_data);
341 void demodulator_logMAP(itpp::vec &extrinsic_data,
const itpp::cvec &rec_sig,
342 const itpp::vec &apriori_data);
344 void demodulator_maxlogMAP(itpp::vec &extrinsic_data,
const itpp::cvec &rec_sig,
345 const itpp::vec &apriori_data);
350 void print_err_msg(
const std::string &msg)
const;
354 struct ITPP_EXPORT MAP_Metrics
356 enum Type {Unknown, logMAP, maxlogMAP, SOVA, Viterbi};
357 MAP_Metrics() : _t(Unknown) {}
358 MAP_Metrics(Type t) : _t(t) {}
359 operator Type ()
const {
return _t;}
362 template<
typename T>
operator T ()
const;
364 MAP_Metrics MAP_metric;
375 double SOVA_scaling_factor;
377 double SOVA_threshold;
379 double Viterbi_scaling_factor[2];
381 bool Viterbi_hard_output_flag;
386 itpp::mat impulse_response;
388 itpp::cmat c_impulse_response;
390 itpp::bvec scrambler_pattern;
392 struct ITPP_EXPORT MUD_Methods
394 enum Type {Unknown, sGCD, maxlogMAP, GCD};
395 MUD_Methods() : _t(Unknown) {}
396 MUD_Methods(Type t) : _t(t) {}
397 operator Type ()
const {
return _t;}
400 template<
typename T>
operator T ()
const;
402 MUD_Methods MUD_method;
407 itpp::cvec constellation;
424 struct ITPP_EXPORT Demapper_Methods
426 enum Type {Unknown, GA, Hassibi_maxlogMAP, sGA, mmsePIC, zfPIC, Alamouti_maxlogMAP};
427 Demapper_Methods() : _t(Unknown) {}
428 Demapper_Methods(Type t) : _t(t) {}
429 operator Type ()
const {
return _t;}
432 template<
typename T>
operator T ()
const;
434 Demapper_Methods demapper_method;
438 void zpFIRfilter(itpp::vec& filt,
443 void gen_chtrellis(
void);
445 void gen_hyperTrellis(
void);
457 void gen_rsctrellis(
void);
468 void gen_nsctrellis(
void);
479 void find_half_const(
int &select_half, itpp::vec &re_part,
482 void EquivRecSig(itpp::vec &x_eq,
const itpp::cmat &rec_sig);
484 void EquivCh(itpp::mat &H_eq,
const itpp::cvec &H);
486 void compute_symb_stats(itpp::vec &Es, itpp::vec &Vs,
487 int ns,
int select_half,
const itpp::vec &apriori_data,
488 const itpp::vec &re_part,
const itpp::vec &im_part,
490 static MAP_Metrics map_metric_from_string(
const std::string &in_MAP_metric);
491 static MUD_Methods mud_method_from_string(
const std::string &in_mud_method);
492 static Demapper_Methods demapper_method_from_string(
const std::string &in_dem_method);
498 MAP_metric = MAP_Metrics::maxlogMAP;
499 MUD_method = MUD_Methods::sGCD;
500 scrambler_pattern =
"0";
502 demapper_method = Demapper_Methods::GA;
503 Viterbi_win_len = 20;
504 SOVA_scaling_factor = 0.8;
506 Viterbi_scaling_factor[0] = 1.4;
507 Viterbi_scaling_factor[1] = 0.4;
508 Viterbi_hard_output_flag =
false;
511 inline SISO::MAP_Metrics SISO::map_metric_from_string(
const std::string &in_MAP_metric)
513 if (in_MAP_metric==
"logMAP")
515 return MAP_Metrics::logMAP;
516 }
else if (in_MAP_metric==
"maxlogMAP")
518 return MAP_Metrics::maxlogMAP;
519 }
else if (in_MAP_metric==
"SOVA")
521 return MAP_Metrics::SOVA;
522 }
else if (in_MAP_metric==
"Viterbi")
524 return MAP_Metrics::Viterbi;
527 return MAP_Metrics::Unknown;
531 inline SISO::MUD_Methods SISO::mud_method_from_string(
const std::string &in_mud_method)
533 if (in_mud_method==
"maxlogMAP")
535 return MUD_Methods::maxlogMAP;
536 }
else if (in_mud_method==
"sGCD")
538 return MUD_Methods::sGCD;
539 }
else if (in_mud_method==
"GCD")
541 return MUD_Methods::GCD;
544 return MUD_Methods::Unknown;
548 inline SISO::Demapper_Methods SISO::demapper_method_from_string(
const std::string &in_dem_method)
550 if (in_dem_method==
"Hassibi_maxlogMAP")
552 return Demapper_Methods::Hassibi_maxlogMAP;
553 }
else if (in_dem_method==
"Alamouti_maxlogMAP")
555 return Demapper_Methods::Alamouti_maxlogMAP;
556 }
else if (in_dem_method==
"GA")
558 return Demapper_Methods::GA;
559 }
else if (in_dem_method==
"sGA")
561 return Demapper_Methods::sGA;
562 }
else if (in_dem_method==
"mmsePIC")
564 return Demapper_Methods::mmsePIC;
565 }
else if (in_dem_method==
"zfPIC")
567 return Demapper_Methods::zfPIC;
570 return Demapper_Methods::Unknown;
576 MAP_metric = map_metric_from_string(in_MAP_metric);
581 prec_gen = in_prec_gen;
585 const int &constraint_length)
596 const int &constraint_length)
598 int nb_outputs = in_gen.length();
599 gen.set_size(nb_outputs, constraint_length);
600 for (
int n=0; n<nb_outputs; n++)
611 Viterbi_win_len = win_len;
616 SOVA_scaling_factor = scaling_factor;
625 const double &nonmatching_scaling_factor)
627 Viterbi_scaling_factor[0] = matching_scaling_factor;
628 Viterbi_scaling_factor[1] = nonmatching_scaling_factor;
633 Viterbi_hard_output_flag = flag;
643 impulse_response.set_size(1, h.length());
644 impulse_response.set_row(0, h);
649 impulse_response = H;
654 c_impulse_response.set_size(1, h.length());
655 c_impulse_response.set_row(0, h);
660 c_impulse_response = cH;
665 int phi_len = phi.length();
666 scrambler_pattern.set_size(phi_len);
669 for (n=0; n<phi_len; n++)
670 scrambler_pattern(n) =
itpp::bin((1-
int(phi(n)))/2);
675 scrambler_pattern = phi;
680 MUD_method = mud_method_from_string(method);
684 const itpp::cvec &in_constellation,
const itpp::bmat &in_bin_constellation)
686 nb_bits_symb = in_nb_bits_symb;
687 constellation = in_constellation;
688 bin_constellation = in_bin_constellation;
692 const itpp::cvec &in_constellation,
const itpp::ivec &in_int_constellation)
694 nb_bits_symb = in_nb_bits_symb;
695 int nb_symb = in_constellation.length();
696 constellation.set_size(nb_symb);
697 bin_constellation.set_size(nb_symb, nb_bits_symb);
698 for (
int n=0; n<nb_symb; n++)
700 constellation(n) = in_constellation(in_int_constellation(n));
701 bin_constellation.set_row(n,
itpp::dec2bin(nb_bits_symb, n));
706 const itpp::cmat &B,
const int &N)
709 nb_em_ant = A.cols();
711 block_duration = A.rows()/Q;
718 demapper_method = demapper_method_from_string(method);
721 inline void SISO::rsc(itpp::vec &extrinsic_coded, itpp::vec &extrinsic_data,
722 const itpp::vec &intrinsic_coded,
const itpp::vec &apriori_data,
const bool &tail)
725 rsc(extrinsic_coded, extrinsic_data, intrinsic_coded, apriori_data);
728 inline void SISO::rsc(itpp::vec &extrinsic_coded, itpp::vec &extrinsic_data,
729 const itpp::vec &intrinsic_coded,
const itpp::vec &apriori_data)
733 print_err_msg(
"SISO::rsc: generator polynomials not initialized");
737 if (MAP_metric==MAP_Metrics::logMAP)
739 rsc_logMAP(extrinsic_coded, extrinsic_data, intrinsic_coded, apriori_data);
740 }
else if (MAP_metric==MAP_Metrics::maxlogMAP)
742 rsc_maxlogMAP(extrinsic_coded, extrinsic_data, intrinsic_coded, apriori_data);
743 }
else if (MAP_metric==MAP_Metrics::SOVA)
746 rsc_sova(extrinsic_data, intrinsic_coded, apriori_data, Viterbi_win_len);
747 }
else if (MAP_metric==MAP_Metrics::Viterbi)
749 rsc_viterbi(extrinsic_coded, extrinsic_data, intrinsic_coded, apriori_data, Viterbi_win_len);
752 print_err_msg(
"SISO::rsc: unknown MAP metric. The MAP metric should be either logMAP or maxlogMAP or SOVA or Viterbi");
756 inline void SISO::nsc(itpp::vec &extrinsic_coded, itpp::vec &extrinsic_data,
757 const itpp::vec &intrinsic_coded,
const itpp::vec &apriori_data,
const bool &tail)
760 nsc(extrinsic_coded, extrinsic_data, intrinsic_coded, apriori_data);
763 inline void SISO::nsc(itpp::vec &extrinsic_coded, itpp::vec &extrinsic_data,
764 const itpp::vec &intrinsic_coded,
const itpp::vec &apriori_data)
768 print_err_msg(
"SISO::nsc: generator polynomials not initialized");
772 if (MAP_metric==MAP_Metrics::logMAP)
773 nsc_logMAP(extrinsic_coded, extrinsic_data, intrinsic_coded, apriori_data);
774 else if (MAP_metric==MAP_Metrics::maxlogMAP)
775 nsc_maxlogMAP(extrinsic_coded, extrinsic_data, intrinsic_coded, apriori_data);
777 print_err_msg(
"SISO::nsc: unknown MAP metric. The MAP metric should be either logMAP or maxlogMAP");
781 const itpp::vec &rec_sig,
782 const itpp::vec &apriori_data,
787 equalizer(extrinsic_data, rec_sig, apriori_data);
791 const itpp::vec &apriori_data)
793 if (impulse_response.size()==0)
795 print_err_msg(
"SISO::equalizer: channel impulse response not initialized");
798 if ((impulse_response.size()==1)&&(prec_gen.length()==1))
800 print_err_msg(
"SISO::equalizer: flat fading channel and no precoder. Use the soft output of the channel (no need for a priori information)");
804 if (MAP_metric==MAP_Metrics::logMAP)
805 equalizer_logMAP(extrinsic_data, rec_sig, apriori_data);
806 else if (MAP_metric==MAP_Metrics::maxlogMAP)
807 equalizer_maxlogMAP(extrinsic_data, rec_sig, apriori_data);
809 print_err_msg(
"SISO::equalizer: unknown MAP metric. The MAP metric should be either logMAP or maxlogMAP");
812 inline void SISO::mud(itpp::mat &extrinsic_data,
const itpp::vec &rec_sig,
813 const itpp::mat &apriori_data)
815 if (impulse_response.size()==0)
817 print_err_msg(
"SISO::mud: channel impulse response not initialized");
820 if (impulse_response.rows()!=apriori_data.rows())
822 print_err_msg(
"SISO::mud: channel impulse response must have the same number of rows as a priori info.");
826 if (MUD_method==MUD_Methods::maxlogMAP)
827 mud_maxlogMAP(extrinsic_data, rec_sig, apriori_data);
828 else if (MUD_method==MUD_Methods::GCD)
829 GCD(extrinsic_data, rec_sig, apriori_data);
830 else if (MUD_method==MUD_Methods::sGCD)
831 sGCD(extrinsic_data, rec_sig, apriori_data);
833 print_err_msg(
"SISO::mud: unknown MUD method. The MUD method should be either maxlogMAP, GCD or sGCD");
837 const itpp::vec &apriori_data)
839 if (c_impulse_response.size()==0)
841 print_err_msg(
"SISO::demapper: channel impulse response not initialized");
844 if ((constellation.size()==0) || (bin_constellation.size()==0))
846 print_err_msg(
"SISO::demapper: constellation not initialized");
849 if (MAP_metric==MAP_Metrics::logMAP)
850 demodulator_logMAP(extrinsic_data, rec_sig, apriori_data);
851 else if (MAP_metric==MAP_Metrics::maxlogMAP)
852 demodulator_maxlogMAP(extrinsic_data, rec_sig, apriori_data);
854 print_err_msg(
"SISO::demapper: unknown MAP metric. The MAP metric should be either logMAP or maxlogMAP");
858 const itpp::vec &apriori_data)
860 if (c_impulse_response.size()==0)
862 print_err_msg(
"SISO::demapper: channel impulse response not initialized");
865 if ((ST_gen1.size()==0) || (ST_gen2.size()==0))
867 print_err_msg(
"SISO::demapper: Space-Time generator polynomials not initialized");
870 if ((constellation.size()==0) || (bin_constellation.size()==0))
872 print_err_msg(
"SISO::demapper: constellation not initialized");
876 if (demapper_method==Demapper_Methods::Hassibi_maxlogMAP)
877 Hassibi_maxlogMAP(extrinsic_data, rec_sig, apriori_data);
878 else if (demapper_method==Demapper_Methods::GA)
879 GA(extrinsic_data, rec_sig, apriori_data);
880 else if (demapper_method==Demapper_Methods::sGA)
881 sGA(extrinsic_data, rec_sig, apriori_data);
882 else if (demapper_method==Demapper_Methods::mmsePIC)
883 mmsePIC(extrinsic_data, rec_sig, apriori_data);
884 else if (demapper_method==Demapper_Methods::zfPIC)
885 zfPIC(extrinsic_data, rec_sig, apriori_data);
886 else if (demapper_method==Demapper_Methods::Alamouti_maxlogMAP)
887 Alamouti_maxlogMAP(extrinsic_data, rec_sig, apriori_data);
889 print_err_msg(
"SISO::demapper: unknown demapper method. The demapper method should be either Hassibi_maxlogMAP, GA, sGA, mmsePIC, zfPIC or Alamouti_maxlogMAP");
892 inline void SISO::print_err_msg(
const std::string &msg)
const
895 mexErrMsgTxt(msg.c_str());
897 std::cout << msg << std::endl;
903 if ((x>value)||(x<-value))
904 return (x>0?value:-value);
908 inline itpp::vec
SISO::threshold(
const itpp::vec &in,
const double &value)
910 itpp::vec out(in.length());
912 for (n=0; n<in.length(); n++)
917 inline itpp::mat
SISO::threshold(
const itpp::mat &in,
const double &value)
919 itpp::mat out(in.rows(),in.cols());
921 for (n=0; n<in.rows(); n++)
922 out.set_row(n,
threshold(in.get_row(n), value));