32 #define INFINITY std::numeric_limits<double>::infinity()
37 void SISO::find_half_const(
int &select_half, itpp::vec &re_part,
itpp::bmat &re_bin_part, itpp::vec &im_part,
itpp::bmat &im_bin_part)
45 int half_nb_bits_symb = nb_bits_symb/2;
49 re_part.set_size(half_len);
50 re_bin_part.set_size(half_len, half_nb_bits_symb);
52 re_part(0) = constellation(0).real();
53 im_part.set_size(half_len);
54 im_bin_part.set_size(half_len, half_nb_bits_symb);
56 im_part(0) = constellation(0).imag();
60 print_err_msg(
"SISO::find_half_const: number of bits per symbol must be a multiple of two");
63 const double min_diff = 1e-3;
65 if (idx.length()!=half_len)
67 print_err_msg(
"SISO::find_half_const: the constellation must be quadratic");
70 itpp::bvec temp(nb_bits_symb);
74 temp = bin_constellation.get_row(idx(n));
75 re_bin_part.set_row(n,temp(0,half_nb_bits_symb-1));
77 select_half = (re_bin_part.get_row(0)==re_bin_part.get_row(1))?0:1;
80 temp = bin_constellation.get_row(0);
81 re_bin_part.set_row(0,temp(select_half*half_nb_bits_symb,(1+select_half)*half_nb_bits_symb-1));
82 im_bin_part.set_row(0,temp((1-select_half)*half_nb_bits_symb,(2-select_half)*half_nb_bits_symb-1));
85 for (n=1; n<const_size; n++)
87 temp = bin_constellation.get_row(n);
88 buffer = constellation(n).real();
92 re_part(re_idx) = buffer;
93 re_bin_part.set_row(re_idx, temp(select_half*half_nb_bits_symb,(1+select_half)*half_nb_bits_symb-1));
95 buffer = constellation(n).imag();
99 im_part(im_idx) = buffer;
100 im_bin_part.set_row(im_idx, temp((1-select_half)*half_nb_bits_symb,(2-select_half)*half_nb_bits_symb-1));
105 void SISO::EquivRecSig(itpp::vec &x_eq,
const itpp::cmat &rec_sig)
113 for (
int k=0; k<nb_rec_ant; k++)
115 x_eq.set_subvector(k*2*block_duration,
itpp::real(rec_sig.get_col(k)));
116 x_eq.set_subvector(k*2*block_duration+block_duration,
itpp::imag(rec_sig.get_col(k)));
120 void SISO::EquivCh(itpp::mat &H_eq,
const itpp::cvec &H)
127 itpp::mat Aq(2*block_duration,2*nb_em_ant);
128 itpp::mat Bq(2*block_duration,2*nb_em_ant);
129 itpp::cmat temp(block_duration,nb_em_ant);
130 itpp::vec h(2*nb_em_ant);
131 itpp::mat AhBh(2*block_duration,2);
133 for (k=0; k<symbols_block; k++)
135 temp = ST_gen1.get(k*block_duration,k*block_duration+block_duration-1,0,nb_em_ant-1);
137 Aq.set_submatrix(0, nb_em_ant, -
itpp::imag(temp));
138 Aq.set_submatrix(block_duration, 0,
itpp::imag(temp));
139 Aq.set_submatrix(block_duration, nb_em_ant,
itpp::real(temp));
140 temp = ST_gen2.get(k*block_duration,k*block_duration+block_duration-1,0,nb_em_ant-1);
142 Bq.set_submatrix(0, nb_em_ant, -
itpp::real(temp));
143 Bq.set_submatrix(block_duration, 0,
itpp::real(temp));
144 Bq.set_submatrix(block_duration, nb_em_ant, -
itpp::imag(temp));
145 for (n=0; n<nb_rec_ant; n++)
147 h.set_subvector(0,
real(H.mid(n*nb_em_ant,nb_em_ant)));
148 h.set_subvector(nb_em_ant,
imag(H.mid(n*nb_em_ant,nb_em_ant)));
149 AhBh.set_col(0, Aq*h);
150 AhBh.set_col(1, Bq*h);
151 H_eq.set_submatrix(2*block_duration*n, 2*k, AhBh);
156 void SISO::compute_symb_stats(itpp::vec &Es, itpp::vec &Vs,
157 int ns,
int select_half,
const itpp::vec &apriori_data,
158 const itpp::vec &re_part,
const itpp::vec &im_part,
161 int half_nb_bits_symb = nb_bits_symb/2;
166 for (
int q = 0; q < symbols_block; q++)
168 int index = q*nb_bits_symb+ns*symbols_block*nb_bits_symb;
169 for (
int k = 0; k < half_len; k++)
172 apriori_data.mid(select_half*half_nb_bits_symb+index,half_nb_bits_symb))),\
173 1+
exp(apriori_data.mid(select_half*half_nb_bits_symb+index,half_nb_bits_symb))));
175 apriori_data.mid((1-select_half)*half_nb_bits_symb+index,half_nb_bits_symb))),\
176 1+
exp(apriori_data.mid((1-select_half)*half_nb_bits_symb+index,half_nb_bits_symb))));
178 apriori_data.mid(select_half*half_nb_bits_symb+index,half_nb_bits_symb))),\
179 1+
exp(apriori_data.mid(select_half*half_nb_bits_symb+index,half_nb_bits_symb))));
181 apriori_data.mid((1-select_half)*half_nb_bits_symb+index,half_nb_bits_symb))),\
182 1+
exp(apriori_data.mid((1-select_half)*half_nb_bits_symb+index,half_nb_bits_symb))));
189 void SISO::Hassibi_maxlogMAP(itpp::vec &extrinsic_data,
const itpp::cmat &rec_sig,
const itpp::vec &apriori_data)
193 int nb_subblocks = rec_sig.rows()/block_duration;
194 double N0 = 2*sigma2;
195 int nb_all_symb =
itpp::pow2i(nb_bits_symb*symbols_block);
197 itpp::bvec bin_frame(nb_bits_symb*symbols_block);
198 itpp::bmat mat_bin_frame(nb_bits_symb, symbols_block);
199 itpp::vec symb_frame_eq(2*symbols_block);
201 itpp::mat H_eq(2*nb_rec_ant*block_duration,2*symbols_block);
202 itpp::vec x_eq(2*block_duration*nb_rec_ant);
203 register int ns,q,nb,n,k;
205 extrinsic_data.set_size(nb_bits_symb*nb_subblocks*symbols_block);
207 for (ns=0; ns<nb_subblocks; ns++)
210 EquivCh(H_eq, c_impulse_response.get_col(ns));
212 EquivRecSig(x_eq, rec_sig(ns*block_duration,(ns+1)*block_duration-1,0,nb_rec_ant-1));
214 for (q=0; q<symbols_block; q++)
216 for (nb=0; nb<nb_bits_symb; nb++)
220 for (n=0; n<nb_all_symb; n++)
223 mat_bin_frame =
itpp::reshape(bin_frame, nb_bits_symb, symbols_block);
224 for (k=0; k<symbols_block; k++)
226 symb_frame_eq(2*k) = constellation(
itpp::bin2dec(mat_bin_frame.get_col(k))).real();
227 symb_frame_eq(1+2*k) = constellation(
itpp::bin2dec(mat_bin_frame.get_col(k))).imag();
230 itpp::to_vec(bin_frame)*apriori_data.mid(ns*nb_bits_symb*symbols_block,nb_bits_symb*symbols_block);
231 if (bin_frame(nb+q*nb_bits_symb))
236 index = nb+q*nb_bits_symb+ns*nb_bits_symb*symbols_block;
237 extrinsic_data(index) = (nom-denom)-apriori_data(index);
243 void SISO::GA(itpp::vec &extrinsic_data,
const itpp::cmat &rec_sig,
const itpp::vec &apriori_data)
247 int nb_subblocks = rec_sig.rows()/block_duration;
248 int half_nb_bits_symb = nb_bits_symb/2;
257 find_half_const(select_half, re_part, re_bin_part, im_part, im_bin_part);
260 itpp::mat H_eq(2*nb_rec_ant*block_duration,2*symbols_block);
261 itpp::vec Es(2*symbols_block);
262 itpp::vec Vs(2*symbols_block);
263 itpp::vec Ey(2*block_duration*nb_rec_ant);
264 itpp::mat Cy(2*block_duration*nb_rec_ant,2*block_duration*nb_rec_ant);
265 itpp::mat Cy_inv(2*block_duration*nb_rec_ant,2*block_duration*nb_rec_ant);
266 itpp::vec x_eq(2*block_duration*nb_rec_ant);
267 itpp::vec EZeta(2*block_duration*nb_rec_ant);
268 itpp::mat CZeta_inv(2*block_duration*nb_rec_ant,2*block_duration*nb_rec_ant);
271 register int ns,q,p,cs;
273 extrinsic_data.set_size(nb_bits_symb*nb_subblocks*symbols_block);
274 for (ns=0; ns<nb_subblocks; ns++)
277 compute_symb_stats(Es, Vs, ns, select_half, apriori_data,
278 re_part, im_part, re_bin_part, im_bin_part);
281 EquivCh(H_eq, c_impulse_response.get_col(ns));
285 Cy = sigma2*
itpp::eye(2*block_duration*nb_rec_ant);
286 for (q=0; q<symbols_block; q++)
289 Ey += (H_eq.get_col(2*q)*Es(2*q)+H_eq.get_col(1+2*q)*Es(1+2*q));
298 EquivRecSig(x_eq, rec_sig(ns*block_duration,(ns+1)*block_duration-1,0,nb_rec_ant-1));
301 for (q=0; q<symbols_block; q++)
304 EZeta = Ey-H_eq.get_col(2*q)*Es(2*q);
306 ((Vs(2*q)/(1-(((H_eq.get_col(2*q)).
transpose()*Cy_inv)*(H_eq.get_col(2*q)*Vs(2*q)))(0)))*\
307 H_eq.get_col(2*q)), Cy_inv.transpose()*H_eq.get_col(2*q));
308 index = select_half*half_nb_bits_symb+q*nb_bits_symb+ns*symbols_block*nb_bits_symb;
309 for (p=0; p<half_nb_bits_symb; p++)
313 for (cs=0; cs<half_len; cs++)
315 temp = -0.5*((x_eq-H_eq.get_col(2*q)*re_part(cs)-EZeta).
transpose()*CZeta_inv*(x_eq-H_eq.get_col(2*q)*re_part(cs)-EZeta))(0)+\
316 itpp::to_vec(re_bin_part.get_row(cs))*apriori_data.mid(index,half_nb_bits_symb);
317 if (re_bin_part(cs,p))
322 extrinsic_data(index+p) = (nom-denom)-apriori_data(index+p);
325 EZeta = Ey-H_eq.get_col(1+2*q)*Es(1+2*q);
327 ((Vs(1+2*q)/(1-(((H_eq.get_col(1+2*q)).
transpose()*Cy_inv)*(H_eq.get_col(1+2*q)*Vs(1+2*q)))(0)))*\
328 H_eq.get_col(1+2*q)), Cy_inv.transpose()*H_eq.get_col(1+2*q));
329 index = (1-select_half)*half_nb_bits_symb+q*nb_bits_symb+ns*symbols_block*nb_bits_symb;
330 for (p=0; p<half_nb_bits_symb; p++)
334 for (cs=0; cs<half_len; cs++)
336 temp = -0.5*((x_eq-H_eq.get_col(1+2*q)*im_part(cs)-EZeta).
transpose()*CZeta_inv*(x_eq-H_eq.get_col(1+2*q)*im_part(cs)-EZeta))(0)+\
337 itpp::to_vec(im_bin_part.get_row(cs))*apriori_data.mid(index,half_nb_bits_symb);
338 if (im_bin_part(cs,p))
343 extrinsic_data(index+p) = (nom-denom)-apriori_data(index+p);
349 void SISO::sGA(itpp::vec &extrinsic_data,
const itpp::cmat &rec_sig,
const itpp::vec &apriori_data)
353 int nb_subblocks = (int)(rec_sig.rows()/block_duration);
354 int half_nb_bits_symb = (int)(nb_bits_symb/2);
363 find_half_const(select_half, re_part, re_bin_part, im_part, im_bin_part);
366 itpp::mat H_eq(2*nb_rec_ant*block_duration,2*symbols_block);
368 itpp::vec Es(2*symbols_block);
369 itpp::vec Vs(2*symbols_block);
370 itpp::vec Ey(2*block_duration*nb_rec_ant);
371 itpp::mat Cy(2*block_duration*nb_rec_ant,2*block_duration*nb_rec_ant);
372 itpp::vec x_eq(2*block_duration*nb_rec_ant);
373 itpp::vec EZeta(2*block_duration*nb_rec_ant);
374 itpp::vec CZeta(2*block_duration*nb_rec_ant);
377 register int ns,q,p,cs;
379 extrinsic_data.set_size(nb_bits_symb*nb_subblocks*symbols_block);
380 for (ns=0; ns<nb_subblocks; ns++)
383 compute_symb_stats(Es, Vs, ns, select_half, apriori_data,
384 re_part, im_part, re_bin_part, im_bin_part);
387 EquivCh(H_eq, c_impulse_response.get_col(ns));
391 Cy = sigma2*
itpp::eye(2*block_duration*nb_rec_ant);
392 for (q=0; q<symbols_block; q++)
395 Ey += (H_eq.get_col(2*q)*Es(2*q)+H_eq.get_col(1+2*q)*Es(1+2*q));
401 EquivRecSig(x_eq, rec_sig(ns*block_duration,(ns+1)*block_duration-1,0,nb_rec_ant-1));
404 for (q=0; q<symbols_block; q++)
407 EZeta = Ey-H_eq.get_col(2*q)*Es(2*q);
409 index = select_half*half_nb_bits_symb+q*nb_bits_symb+ns*symbols_block*nb_bits_symb;
410 for (p=0; p<half_nb_bits_symb; p++)
414 for (cs=0; cs<half_len; cs++)
417 itpp::to_vec(re_bin_part.get_row(cs))*apriori_data.mid(index,half_nb_bits_symb);
418 if (re_bin_part(cs,p))
423 extrinsic_data(index+p) = (nom-denom)-apriori_data(index+p);
426 EZeta = Ey-H_eq.get_col(1+2*q)*Es(1+2*q);
428 index = (1-select_half)*half_nb_bits_symb+q*nb_bits_symb+ns*symbols_block*nb_bits_symb;
429 for (p=0; p<half_nb_bits_symb; p++)
433 for (cs=0; cs<half_len; cs++)
436 itpp::to_vec(im_bin_part.get_row(cs))*apriori_data.mid(index,half_nb_bits_symb);
437 if (im_bin_part(cs,p))
442 extrinsic_data(index+p) = (nom-denom)-apriori_data(index+p);
448 void SISO::mmsePIC(itpp::vec &extrinsic_data,
const itpp::cmat &rec_sig,
const itpp::vec &apriori_data)
452 int nb_subblocks = rec_sig.rows()/block_duration;
453 int half_nb_bits_symb = nb_bits_symb/2;
454 int half_const_len =
itpp::pow2i(half_nb_bits_symb);
455 int nb_bits_subblock = nb_bits_symb*symbols_block;
456 itpp::vec Es(2*symbols_block);
457 itpp::vec Vs(2*symbols_block);
458 itpp::mat H_eq(2*nb_rec_ant*block_duration,2*symbols_block);
459 itpp::mat K(2*nb_rec_ant*block_duration,2*nb_rec_ant*block_duration);
460 itpp::mat K_inv(2*nb_rec_ant*block_duration,2*nb_rec_ant*block_duration);
461 itpp::vec x_eq(2*nb_rec_ant*block_duration);
462 itpp::vec interf(2*symbols_block);
463 itpp::vec temp(2*nb_rec_ant*block_duration);
464 itpp::vec w(2*nb_rec_ant*block_duration);
470 register int ns,q,k,s;
479 find_half_const(select_half, re_part, re_bin_part, im_part, im_bin_part);
480 double part_var = 1/(double)(2*nb_em_ant);
482 extrinsic_data.set_size(nb_bits_symb*nb_subblocks*symbols_block);
483 for (ns=0; ns<nb_subblocks; ns++)
486 compute_symb_stats(Es, Vs, ns, select_half, apriori_data,
487 re_part, im_part, re_bin_part, im_bin_part);
490 EquivCh(H_eq, c_impulse_response.get_col(ns));
495 EquivRecSig(x_eq, rec_sig(ns*block_duration,(ns+1)*block_duration-1,0,nb_rec_ant-1));
496 for (q=0; q<symbols_block; q++)
503 temp = H_eq.get_col(2*q);
505 (1+((temp.transpose()*K_inv)*(temp*(part_var-Vs(2*q))))(0)))*temp), K_inv.transpose()*temp));
506 s_tilde = w*(x_eq-H_eq*interf);
508 index = select_half*half_nb_bits_symb+nb_bits_symb*q+ns*nb_bits_subblock;
509 for (k=0; k<half_nb_bits_symb; k++)
513 for (s=0; s<half_const_len; s++)
516 tmp = -
itpp::sqr(s_tilde-mu_res*re_part(s))/(2*sigma2_res)+ \
517 itpp::to_vec(re_bin_part.get_row(s))*apriori_data.mid(index, half_nb_bits_symb);
518 if (re_bin_part(s,k))
523 extrinsic_data(index+k) = (nom-denom)-apriori_data(index+k);
530 temp = H_eq.get_col(2*q+1);
532 (1+((temp.transpose()*K_inv)*(temp*(part_var-Vs(1+2*q))))(0)))*temp), K_inv.transpose()*temp));
533 s_tilde = w*(x_eq-H_eq*interf);
535 index = (1-select_half)*half_nb_bits_symb+nb_bits_symb*q+ns*nb_bits_subblock;
536 for (k=0; k<half_nb_bits_symb; k++)
540 for (s=0; s<half_const_len; s++)
543 tmp = -
itpp::sqr(s_tilde-mu_res*im_part(s))/(2*sigma2_res)+ \
544 itpp::to_vec(im_bin_part.get_row(s))*apriori_data.mid(index, half_nb_bits_symb);
545 if (im_bin_part(s,k))
550 extrinsic_data(index+k) = (nom-denom)-apriori_data(index+k);
557 void SISO::zfPIC(itpp::vec &extrinsic_data,
const itpp::cmat &rec_sig,
const itpp::vec &apriori_data)
561 int nb_subblocks = rec_sig.rows()/block_duration;
562 int half_nb_bits_symb = nb_bits_symb/2;
563 int half_const_len =
itpp::pow2i(half_nb_bits_symb);
564 int nb_bits_subblock = nb_bits_symb*symbols_block;
565 itpp::vec Es(2*symbols_block);
566 itpp::vec Vs(2*symbols_block);
567 itpp::mat H_eq(2*nb_rec_ant*block_duration,2*symbols_block);
568 itpp::mat K(2*nb_rec_ant*block_duration,2*nb_rec_ant*block_duration);
569 itpp::vec x_eq(2*nb_rec_ant*block_duration);
570 itpp::vec interf(2*symbols_block);
571 itpp::vec temp(2*nb_rec_ant*block_duration);
572 itpp::vec w(2*nb_rec_ant*block_duration);
578 register int ns,q,k,s;
587 find_half_const(select_half, re_part, re_bin_part, im_part, im_bin_part);
589 extrinsic_data.set_size(nb_bits_symb*nb_subblocks*symbols_block);
590 for (ns=0; ns<nb_subblocks; ns++)
593 compute_symb_stats(Es, Vs, ns, select_half, apriori_data,
594 re_part, im_part, re_bin_part, im_bin_part);
597 EquivCh(H_eq, c_impulse_response.get_col(ns));
601 EquivRecSig(x_eq, rec_sig(ns*block_duration,(ns+1)*block_duration-1,0,nb_rec_ant-1));
602 for (q=0; q<symbols_block; q++)
609 temp = H_eq.get_col(2*q);
610 w = temp/(temp*temp);
611 s_tilde = w*(x_eq-H_eq*interf);
613 index = select_half*half_nb_bits_symb+nb_bits_symb*q+ns*nb_bits_subblock;
614 for (k=0; k<half_nb_bits_symb; k++)
618 for (s=0; s<half_const_len; s++)
621 tmp = -
itpp::sqr(s_tilde-mu_res*re_part(s))/(2*sigma2_res)+ \
622 itpp::to_vec(re_bin_part.get_row(s))*apriori_data.mid(index, half_nb_bits_symb);
623 if (re_bin_part(s,k))
628 extrinsic_data(index+k) = (nom-denom)-apriori_data(index+k);
635 temp = H_eq.get_col(2*q+1);
636 w = temp/(temp*temp);
637 s_tilde = w*(x_eq-H_eq*interf);
639 index = (1-select_half)*half_nb_bits_symb+nb_bits_symb*q+ns*nb_bits_subblock;
640 for (k=0; k<half_nb_bits_symb; k++)
644 for (s=0; s<half_const_len; s++)
647 tmp = -
itpp::sqr(s_tilde-mu_res*im_part(s))/(2*sigma2_res)+ \
648 itpp::to_vec(im_bin_part.get_row(s))*apriori_data.mid(index, half_nb_bits_symb);
649 if (im_bin_part(s,k))
654 extrinsic_data(index+k) = (nom-denom)-apriori_data(index+k);
661 void SISO::Alamouti_maxlogMAP(itpp::vec &extrinsic_data,
const itpp::cmat &rec_sig,
const itpp::vec &apriori_data)
665 int int_len = apriori_data.length();
666 int nb_symb = (int)(int_len/nb_bits_symb);
667 itpp::cvec comb_sig(nb_symb);
669 itpp::cmat conj_H =
itpp::conj(c_impulse_response);
671 register int nr,n,cs;
672 for (nr=0; nr<nb_rec_ant; nr++)
674 for (n=0; n<(nb_symb/2); n++)
676 comb_sig(2*n) += (conj_H(2*nr,n)*rec_sig(2*n,nr)+c_impulse_response(1+2*nr,n)*conj_X(1+2*n,nr));
677 comb_sig(1+2*n) += (conj_H(1+2*nr,n)*rec_sig(2*n,nr)-c_impulse_response(2*nr,n)*conj_X(1+2*n,nr));
687 extrinsic_data.set_size(nb_bits_symb*nb_symb);
688 for (n=0; n<nb_symb; n++)
691 for (nr=0; nr<nb_bits_symb; nr++)
695 for (cs=0; cs<const_size; cs++)
697 temp = -
itpp::sqr(comb_sig(n)-buffer*constellation(cs))/(2*buffer*sigma2)+ \
698 itpp::to_vec(bin_constellation.get_row(cs))*apriori_data.mid(n*nb_bits_symb, nb_bits_symb);
699 if (bin_constellation(cs,nr))
704 index = n*nb_bits_symb+nr;
705 extrinsic_data(index) = (nom-denom)-apriori_data(index);
710 void SISO::demodulator_logMAP(itpp::vec &extrinsic_data,
const itpp::cvec &rec_sig,
const itpp::vec &apriori_data)
713 int nb_symb = rec_sig.length();
715 double nom,denom,temp;
718 extrinsic_data.set_size(nb_bits_symb*nb_symb);
719 for (k=0; k<nb_symb; k++)
721 for (i=0; i<nb_bits_symb; i++)
725 for (cs=0; cs<const_size; cs++)
727 temp = -
itpp::sqr(rec_sig(k)-c_impulse_response(0,k)*constellation(cs))/(2*sigma2)+\
728 itpp::to_vec(bin_constellation.get_row(cs))*apriori_data.mid(k*nb_bits_symb, nb_bits_symb);
729 if (bin_constellation(cs,i))
734 index = k*nb_bits_symb+i;
735 extrinsic_data(index) =
std::log(nom/denom)-apriori_data(index);
740 void SISO::demodulator_maxlogMAP(itpp::vec &extrinsic_data,
const itpp::cvec &rec_sig,
const itpp::vec &apriori_data)
743 int nb_symb = rec_sig.length();
745 double nom,denom,temp;
748 extrinsic_data.set_size(nb_bits_symb*nb_symb);
749 for (k=0; k<nb_symb; k++)
751 for (i=0; i<nb_bits_symb; i++)
755 for (cs=0; cs<const_size; cs++)
757 temp = -
itpp::sqr(rec_sig(k)-c_impulse_response(0,k)*constellation(cs))/(2*sigma2)+\
758 itpp::to_vec(bin_constellation.get_row(cs))*apriori_data.mid(k*nb_bits_symb, nb_bits_symb);
759 if (bin_constellation(cs,i))
764 index = k*nb_bits_symb+i;
765 extrinsic_data(index) = (nom-denom)-apriori_data(index);