IT++ Logo
siso_dem.cpp
Go to the documentation of this file.
1 
29 #include <itpp/comm/siso.h>
30 #include <limits>
31 #ifndef INFINITY
32 #define INFINITY std::numeric_limits<double>::infinity()
33 #endif
34 
35 namespace itpp
36 {
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)
38 /* finds real in imaginary parts of the constellation and its corresponding bits
39  * this approach is used for equivalent channel according to Hassibi's model
40  * the constellation must be quadratic and the number of bits per symbol must be a multiple of two
41  */
42 {
43  //values needed for initializations
44  int const_size = itpp::pow2i(nb_bits_symb);//constellation size
45  int half_nb_bits_symb = nb_bits_symb/2;
46  int half_len = itpp::pow2i(half_nb_bits_symb);//number of values of real(imaginary) part
47  //initialize output variables
48  select_half = 0;
49  re_part.set_size(half_len);
50  re_bin_part.set_size(half_len, half_nb_bits_symb);
51  re_part.zeros();
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);
55  im_part.zeros();
56  im_part(0) = constellation(0).imag();
57  //select half for real (imaginary) to binary correspondence
58  if (nb_bits_symb%2)
59  {
60  print_err_msg("SISO::find_half_const: number of bits per symbol must be a multiple of two");
61  return;
62  }
63  const double min_diff = 1e-3;
64  itpp::ivec idx = itpp::find(itpp::abs(itpp::real(constellation)-re_part(0))<min_diff);
65  if (idx.length()!=half_len)
66  {
67  print_err_msg("SISO::find_half_const: the constellation must be quadratic");
68  return;
69  }
70  itpp::bvec temp(nb_bits_symb);
71  register int n;
72  for (n=0; n<2; n++)
73  {
74  temp = bin_constellation.get_row(idx(n));
75  re_bin_part.set_row(n,temp(0,half_nb_bits_symb-1));
76  }
77  select_half = (re_bin_part.get_row(0)==re_bin_part.get_row(1))?0:1;
78  //algorithm
79  double buffer;
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));
83  int re_idx = 0;
84  int im_idx = 0;
85  for (n=1; n<const_size; n++)
86  {
87  temp = bin_constellation.get_row(n);
88  buffer = constellation(n).real();
89  if (fabs(itpp::prod(re_part-buffer))>min_diff)
90  {
91  re_idx++;
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));
94  }
95  buffer = constellation(n).imag();
96  if (fabs(itpp::prod(im_part-buffer))>min_diff)
97  {
98  im_idx++;
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));
101  }
102  }
103 }
104 
105 void SISO::EquivRecSig(itpp::vec &x_eq, const itpp::cmat &rec_sig)
106 //finds equivalent received signal with real coefficients
107 //the equivalent received signal follows the model of Hassibi's paper
108 //ouput:
109 //x_eq - equivalent received signal with real coefficients
110 //inputs:
111 //rec_sig - received signal
112 {
113  for (int k=0; k<nb_rec_ant; k++)
114  {
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)));
117  }
118 }
119 
120 void SISO::EquivCh(itpp::mat &H_eq, const itpp::cvec &H)
121 //finds equivalent channel with real coefficients following the model of Hassibi's paper
122 //output:
123 //H_eq - equivalent channel
124 //input:
125 //H - channel matrix
126 {
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);
132  register int n,k;
133  for (k=0; k<symbols_block; k++)
134  {
135  temp = ST_gen1.get(k*block_duration,k*block_duration+block_duration-1,0,nb_em_ant-1);
136  Aq.set_submatrix(0, 0, itpp::real(temp));
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);
141  Bq.set_submatrix(0, 0, -itpp::imag(temp));
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++)
146  {
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);
152  }
153  }
154 }
155 
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,
159  const itpp::bmat &re_bin_part, const itpp::bmat &im_bin_part)
160 {
161  int half_nb_bits_symb = nb_bits_symb/2;
162  int half_len = itpp::pow2i(half_nb_bits_symb);//number of values of real(imaginary) part
163 
164  Es.zeros();
165  Vs.zeros();
166  for (int q = 0; q < symbols_block; q++)
167  {
168  int index = q*nb_bits_symb+ns*symbols_block*nb_bits_symb;
169  for (int k = 0; k < half_len; k++)
170  {
171  Es(2*q) += re_part(k)*itpp::prod(itpp::elem_div(exp(itpp::elem_mult(itpp::to_vec(re_bin_part.get_row(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))));
174  Es(1+2*q) += im_part(k)*itpp::prod(itpp::elem_div(exp(itpp::elem_mult(itpp::to_vec(im_bin_part.get_row(k)),\
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))));
177  Vs(2*q) += itpp::sqr(re_part(k))*itpp::prod(itpp::elem_div(exp(itpp::elem_mult(itpp::to_vec(re_bin_part.get_row(k)),\
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))));
180  Vs(1+2*q) += itpp::sqr(im_part(k))*itpp::prod(itpp::elem_div(exp(itpp::elem_mult(itpp::to_vec(im_bin_part.get_row(k)),\
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))));
183  }
184  Vs(2*q) -= itpp::sqr(Es(2*q));
185  Vs(1+2*q) -= itpp::sqr(Es(1+2*q));
186  }
187 }
188 
189 void SISO::Hassibi_maxlogMAP(itpp::vec &extrinsic_data, const itpp::cmat &rec_sig, const itpp::vec &apriori_data)
190 //maxlogMAP algorithm for ST block codes using Hassibi's model
191 {
192  //general parameters
193  int nb_subblocks = rec_sig.rows()/block_duration;//number of subblocks of ST matrices/int period
194  double N0 = 2*sigma2;//noise DSP
195  int nb_all_symb = itpp::pow2i(nb_bits_symb*symbols_block);//nb. of all possible input symbols as a binary vector
196  double nom,denom;//nominator and denominator of extrinsic information
197  itpp::bvec bin_frame(nb_bits_symb*symbols_block);//binary frame at channel input
198  itpp::bmat mat_bin_frame(nb_bits_symb, symbols_block);
199  itpp::vec symb_frame_eq(2*symbols_block);//frame of symbols at equivalent channel input
200  double temp;
201  itpp::mat H_eq(2*nb_rec_ant*block_duration,2*symbols_block);//equivalent channel matrix
202  itpp::vec x_eq(2*block_duration*nb_rec_ant);//equivalent received signal
203  register int ns,q,nb,n,k;
204  int index;
205  extrinsic_data.set_size(nb_bits_symb*nb_subblocks*symbols_block);
206  //main loop
207  for (ns=0; ns<nb_subblocks; ns++)//for each subblock
208  {
209  //find equivalent channel matrix
210  EquivCh(H_eq, c_impulse_response.get_col(ns));
211  //find equivalent received signal
212  EquivRecSig(x_eq, rec_sig(ns*block_duration,(ns+1)*block_duration-1,0,nb_rec_ant-1));
213  //compute the LLR of each bit in a frame of symbols_block symbols
214  for (q=0; q<symbols_block; q++)//for each symbol in a subblock
215  {
216  for (nb=0; nb<nb_bits_symb; nb++)//for a given bit try all possible sollutions for the input symbol vector
217  {
218  nom = -INFINITY;
219  denom = -INFINITY;
220  for (n=0; n<nb_all_symb; n++)//all possible symbols
221  {
222  bin_frame = itpp::dec2bin(nb_bits_symb*symbols_block, n);
223  mat_bin_frame = itpp::reshape(bin_frame, nb_bits_symb, symbols_block);
224  for (k=0; k<symbols_block; k++)
225  {
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();
228  }
229  temp = -itpp::sum_sqr(x_eq-H_eq*symb_frame_eq)/N0+\
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))
232  nom = std::max(nom, temp);
233  else
234  denom = std::max(denom, temp);
235  }
236  index = nb+q*nb_bits_symb+ns*nb_bits_symb*symbols_block;
237  extrinsic_data(index) = (nom-denom)-apriori_data(index);
238  }//bits/symbol
239  }//symbols/subblock
240  }//subblocks
241 }
242 
243 void SISO::GA(itpp::vec &extrinsic_data, const itpp::cmat &rec_sig, const itpp::vec &apriori_data)
244 // Gaussian Approximation algorithm for ST codes using Hassibi's model
245 {
246  //general parameters
247  int nb_subblocks = rec_sig.rows()/block_duration;//number of subblocks
248  int half_nb_bits_symb = nb_bits_symb/2;
249  int half_len = itpp::pow2i(half_nb_bits_symb);//number of values of real(imaginary) part
250 
251  //correspondence between real and imaginary part of symbols and their binary representations
252  int select_half;
253  itpp::vec re_part;
254  itpp::bmat re_bin_part;
255  itpp::vec im_part;
256  itpp::bmat im_bin_part;
257  find_half_const(select_half, re_part, re_bin_part, im_part, im_bin_part);
258 
259  //equivalent channel
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);
269  double nom,denom;
270  double temp;
271  register int ns,q,p,cs;
272  int index;
273  extrinsic_data.set_size(nb_bits_symb*nb_subblocks*symbols_block);
274  for (ns=0; ns<nb_subblocks; ns++)//subblock by subblock
275  {
276  //mean and variance of real and imaginary parts of emitted symbols
277  compute_symb_stats(Es, Vs, ns, select_half, apriori_data,
278  re_part, im_part, re_bin_part, im_bin_part);
279 
280  //find equivalent channel
281  EquivCh(H_eq, c_impulse_response.get_col(ns));
282 
283  //compute E[y] and Cov[y]
284  Ey.zeros();
285  Cy = sigma2*itpp::eye(2*block_duration*nb_rec_ant);
286  for (q=0; q<symbols_block; q++)
287  {
288  //real & imaginary
289  Ey += (H_eq.get_col(2*q)*Es(2*q)+H_eq.get_col(1+2*q)*Es(1+2*q));
290  Cy += (itpp::outer_product(H_eq.get_col(2*q), H_eq.get_col(2*q)*Vs(2*q))+\
291  itpp::outer_product(H_eq.get_col(1+2*q), H_eq.get_col(1+2*q)*Vs(1+2*q)));
292  }
293 
294  //inverse of Cov[y]
295  Cy_inv = itpp::inv(Cy);
296 
297  //find equivalent received signal
298  EquivRecSig(x_eq, rec_sig(ns*block_duration,(ns+1)*block_duration-1,0,nb_rec_ant-1));
299 
300  //compute extrinsic information of coded bits
301  for (q=0; q<symbols_block; q++)
302  {
303  //real part
304  EZeta = Ey-H_eq.get_col(2*q)*Es(2*q);
305  CZeta_inv = Cy_inv+itpp::outer_product(Cy_inv*\
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++)
310  {
311  nom = -INFINITY;
312  denom = -INFINITY;
313  for (cs=0; cs<half_len; cs++)
314  {
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))
318  nom = std::max(nom, temp);
319  else
320  denom = std::max(denom, temp);
321  }
322  extrinsic_data(index+p) = (nom-denom)-apriori_data(index+p);
323  }
324  //imaginary part
325  EZeta = Ey-H_eq.get_col(1+2*q)*Es(1+2*q);
326  CZeta_inv = Cy_inv+itpp::outer_product(Cy_inv*\
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++)
331  {
332  nom = -INFINITY;
333  denom = -INFINITY;
334  for (cs=0; cs<half_len; cs++)
335  {
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))
339  nom = std::max(nom, temp);
340  else
341  denom = std::max(denom, temp);
342  }
343  extrinsic_data(index+p) = (nom-denom)-apriori_data(index+p);
344  }
345  }
346  }//subblock by subblock
347 }
348 
349 void SISO::sGA(itpp::vec &extrinsic_data, const itpp::cmat &rec_sig, const itpp::vec &apriori_data)
350 //simplified Gaussian Approximation algorithm for ST codes using Hassibi's model
351 {
352  //general parameters
353  int nb_subblocks = (int)(rec_sig.rows()/block_duration);//number of subblocks
354  int half_nb_bits_symb = (int)(nb_bits_symb/2);
355  int half_len = itpp::pow2i(half_nb_bits_symb);//number of values of real(imaginary) part
356 
357  //correspondence between real and imaginary part of symbols and their binary representations
358  int select_half;
359  itpp::vec re_part;
360  itpp::bmat re_bin_part;
361  itpp::vec im_part;
362  itpp::bmat im_bin_part;
363  find_half_const(select_half, re_part, re_bin_part, im_part, im_bin_part);
364 
365  //equivalent channel
366  itpp::mat H_eq(2*nb_rec_ant*block_duration,2*symbols_block);
367 
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);
375  double nom,denom;
376  double temp;
377  register int ns,q,p,cs;
378  int index;
379  extrinsic_data.set_size(nb_bits_symb*nb_subblocks*symbols_block);
380  for (ns=0; ns<nb_subblocks; ns++)//subblock by subblock
381  {
382  //mean and variance of real and imaginary parts of emitted symbols
383  compute_symb_stats(Es, Vs, ns, select_half, apriori_data,
384  re_part, im_part, re_bin_part, im_bin_part);
385 
386  //find equivalent channel
387  EquivCh(H_eq, c_impulse_response.get_col(ns));
388 
389  //compute E[y] and Cov[y]
390  Ey.zeros();
391  Cy = sigma2*itpp::eye(2*block_duration*nb_rec_ant);
392  for (q=0; q<symbols_block; q++)
393  {
394  //real & imaginary
395  Ey += (H_eq.get_col(2*q)*Es(2*q)+H_eq.get_col(1+2*q)*Es(1+2*q));
396  Cy += (itpp::outer_product(H_eq.get_col(2*q), H_eq.get_col(2*q)*Vs(2*q))+\
397  itpp::outer_product(H_eq.get_col(1+2*q), H_eq.get_col(1+2*q)*Vs(1+2*q)));
398  }
399 
400  //find equivalent received signal
401  EquivRecSig(x_eq, rec_sig(ns*block_duration,(ns+1)*block_duration-1,0,nb_rec_ant-1));
402 
403  //compute extrinsic INFINITYormation of coded bits
404  for (q=0; q<symbols_block; q++)
405  {
406  //real part
407  EZeta = Ey-H_eq.get_col(2*q)*Es(2*q);
408  CZeta = diag(Cy-itpp::outer_product(H_eq.get_col(2*q), H_eq.get_col(2*q)*Vs(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++)
411  {
412  nom = -INFINITY;
413  denom = -INFINITY;
414  for (cs=0; cs<half_len; cs++)
415  {
416  temp = -0.5*itpp::sum(itpp::elem_div(sqr(x_eq-H_eq.get_col(2*q)*re_part(cs)-EZeta), CZeta))+\
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))
419  nom = std::max(nom, temp);
420  else
421  denom = std::max(denom, temp);
422  }
423  extrinsic_data(index+p) = (nom-denom)-apriori_data(index+p);
424  }
425  //imaginary part
426  EZeta = Ey-H_eq.get_col(1+2*q)*Es(1+2*q);
427  CZeta = itpp::diag(Cy-itpp::outer_product(H_eq.get_col(1+2*q), H_eq.get_col(1+2*q)*Vs(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++)
430  {
431  nom = -INFINITY;
432  denom = -INFINITY;
433  for (cs=0; cs<half_len; cs++)
434  {
435  temp = -0.5*itpp::sum(itpp::elem_div(sqr(x_eq-H_eq.get_col(1+2*q)*im_part(cs)-EZeta), CZeta))+\
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))
438  nom = std::max(nom, temp);
439  else
440  denom = std::max(denom, temp);
441  }
442  extrinsic_data(index+p) = (nom-denom)-apriori_data(index+p);
443  }
444  }
445  }//subblock by subblock
446 }
447 
448 void SISO::mmsePIC(itpp::vec &extrinsic_data, const itpp::cmat &rec_sig, const itpp::vec &apriori_data)
449 //MMSE Parallel Interference Canceller
450 {
451  //general parameters
452  int nb_subblocks = rec_sig.rows()/block_duration;//number of subblocks
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;//number of coded bits in an ST 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);//filter impulse response
465  double s_tilde;
466  double mu_res;
467  double sigma2_res;
468  double nom,denom;
469  double tmp;
470  register int ns,q,k,s;
471  int index;
472 
473  //correspondence between real and imaginary part of symbols and their binary representations
474  int select_half;
475  itpp::vec re_part;
476  itpp::bmat re_bin_part;
477  itpp::vec im_part;
478  itpp::bmat im_bin_part;
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);//real and imaginary part variance
481 
482  extrinsic_data.set_size(nb_bits_symb*nb_subblocks*symbols_block);
483  for (ns=0; ns<nb_subblocks; ns++)//compute block by block
484  {
485  //mean and variance of real and imaginary parts of emitted symbols
486  compute_symb_stats(Es, Vs, ns, select_half, apriori_data,
487  re_part, im_part, re_bin_part, im_bin_part);
488 
489  //find equivalent channel matrix
490  EquivCh(H_eq, c_impulse_response.get_col(ns));
491  //compute invariant inverse
492  K = H_eq*diag(Vs)*H_eq.transpose()+sigma2*itpp::eye(2*block_duration*nb_rec_ant);
493  K_inv = itpp::inv(K);
494  //find equivalent received signal
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++)//symbols/block
497  {
498  //compute the extrinsic information of coded bits
499  //real part
500  //IC + filtering (real and imaginary parts of one symbol)
501  interf = Es;
502  interf(2*q) = 0;//this is the symbol to recover
503  temp = H_eq.get_col(2*q);
504  w = (part_var*temp.transpose())*(K_inv-itpp::outer_product(K_inv*(((part_var-Vs(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);
507  mu_res = w*temp;//mean of the filtered signal
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++)
510  {
511  nom = -INFINITY;
512  denom = -INFINITY;
513  for (s=0; s<half_const_len; s++)
514  {
515  sigma2_res = ((w.transpose()*(K+itpp::outer_product(temp, temp*(itpp::sqr(re_part(s))-Vs(2*q)))))*w)(0)-itpp::sqr(re_part(s)*mu_res);//variance of the filtered signal
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))
519  nom = std::max(nom, tmp);
520  else
521  denom = std::max(denom, tmp);
522  }
523  extrinsic_data(index+k) = (nom-denom)-apriori_data(index+k);
524  }
525  //end real part
526  //imaginary part
527  //IC + filtering (real and imaginary parts of one symbol)
528  interf = Es;
529  interf(2*q+1) = 0;//this is the symbol to recover
530  temp = H_eq.get_col(2*q+1);
531  w = (part_var*temp.transpose())*(K_inv-itpp::outer_product(K_inv*(((part_var-Vs(1+2*q))/ \
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);
534  mu_res = w*temp;//mean of the filtered signal
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++)
537  {
538  nom = -INFINITY;
539  denom = -INFINITY;
540  for (s=0; s<half_const_len; s++)
541  {
542  sigma2_res = ((w.transpose()*(K+itpp::outer_product(temp, temp*(itpp::sqr(im_part(s))-Vs(1+2*q)))))*w)(0)-itpp::sqr(im_part(s)*mu_res);//variance of the filtered signal
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))
546  nom = std::max(nom, tmp);
547  else
548  denom = std::max(denom, tmp);
549  }
550  extrinsic_data(index+k) = (nom-denom)-apriori_data(index+k);
551  }
552  //end imaginary part
553  }//symbols/block
554  }//block by block
555 }
556 
557 void SISO::zfPIC(itpp::vec &extrinsic_data, const itpp::cmat &rec_sig, const itpp::vec &apriori_data)
558 //ZF Parallel Interference Canceller
559 {
560  //general parameters
561  int nb_subblocks = rec_sig.rows()/block_duration;//number of subblocks
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;//number of coded bits in an ST 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);//filter impulse response
573  double s_tilde;
574  double mu_res;
575  double sigma2_res;
576  double nom,denom;
577  double tmp;
578  register int ns,q,k,s;
579  int index;
580 
581  //correspondence between real and imaginary part of symbols and their binary representations
582  int select_half;
583  itpp::vec re_part;
584  itpp::bmat re_bin_part;
585  itpp::vec im_part;
586  itpp::bmat im_bin_part;
587  find_half_const(select_half, re_part, re_bin_part, im_part, im_bin_part);
588 
589  extrinsic_data.set_size(nb_bits_symb*nb_subblocks*symbols_block);
590  for (ns=0; ns<nb_subblocks; ns++)//compute block by block
591  {
592  //mean and variance of real and imaginary parts of emitted symbols
593  compute_symb_stats(Es, Vs, ns, select_half, apriori_data,
594  re_part, im_part, re_bin_part, im_bin_part);
595 
596  //find equivalent channel matrix
597  EquivCh(H_eq, c_impulse_response.get_col(ns));
598  //compute invariant inverse
599  K = H_eq*itpp::diag(Vs)*H_eq.transpose()+sigma2*itpp::eye(2*block_duration*nb_rec_ant);
600  //find equivalent received signal
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++)//symbols/block
603  {
604  //compute the extrinsic information of coded bits
605  //real part
606  //IC + filtering (real and imaginary parts of one symbol)
607  interf = Es;
608  interf(2*q) = 0;//this is the symbol to recover
609  temp = H_eq.get_col(2*q);
610  w = temp/(temp*temp);//filter impulse response
611  s_tilde = w*(x_eq-H_eq*interf);
612  mu_res = w*temp;//mean of the filtered signal
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++)
615  {
616  nom = -INFINITY;
617  denom = -INFINITY;
618  for (s=0; s<half_const_len; s++)
619  {
620  sigma2_res = ((w.transpose()*(K+itpp::outer_product(temp, temp*(itpp::sqr(re_part(s))-Vs(2*q)))))*w)(0)-itpp::sqr(re_part(s)*mu_res);
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))
624  nom = std::max(nom, tmp);
625  else
626  denom = std::max(denom, tmp);
627  }
628  extrinsic_data(index+k) = (nom-denom)-apriori_data(index+k);
629  }
630  //end real part
631  //imaginary part
632  //IC + filtering (real and imaginary parts of one symbol)
633  interf = Es;
634  interf(2*q+1) = 0;//this is the symbol to recover
635  temp = H_eq.get_col(2*q+1);
636  w = temp/(temp*temp);//filter impulse response
637  s_tilde = w*(x_eq-H_eq*interf);
638  mu_res = w*temp;//mean of the filtered signal
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++)
641  {
642  nom = -INFINITY;
643  denom = -INFINITY;
644  for (s=0; s<half_const_len; s++)
645  {
646  sigma2_res = ((w.transpose()*(K+itpp::outer_product(temp, temp*(itpp::sqr(im_part(s))-Vs(1+2*q)))))*w)(0)-itpp::sqr(im_part(s)*mu_res);
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))
650  nom = std::max(nom, tmp);
651  else
652  denom = std::max(denom, tmp);
653  }
654  extrinsic_data(index+k) = (nom-denom)-apriori_data(index+k);
655  }
656  //end imaginary part
657  }//symbols/block
658  }//block by block
659 }
660 
661 void SISO::Alamouti_maxlogMAP(itpp::vec &extrinsic_data, const itpp::cmat &rec_sig, const itpp::vec &apriori_data)
662 //maxlogMAP algorithm for Alamouti ST code
663 {
664  //matched filter
665  int int_len = apriori_data.length();//interleaver length
666  int nb_symb = (int)(int_len/nb_bits_symb);//number of symbols/block
667  itpp::cvec comb_sig(nb_symb);
668  comb_sig.zeros();
669  itpp::cmat conj_H = itpp::conj(c_impulse_response);
670  itpp::cmat conj_X = itpp::conj(rec_sig);
671  register int nr,n,cs;
672  for (nr=0; nr<nb_rec_ant; nr++)
673  {
674  for (n=0; n<(nb_symb/2); n++)
675  {
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));
678  }
679  }
680 
681  //extrinsic information of coded bits
682  int const_size = itpp::pow2i(nb_bits_symb);//constellation size
683  double buffer;
684  double nom,denom;
685  double temp;
686  int index;
687  extrinsic_data.set_size(nb_bits_symb*nb_symb);
688  for (n=0; n<nb_symb; n++)
689  {
690  buffer = itpp::sum_sqr(itpp::abs(c_impulse_response.get_col(n/2)));
691  for (nr=0; nr<nb_bits_symb; nr++)
692  {
693  nom = -INFINITY;
694  denom = -INFINITY;
695  for (cs=0; cs<const_size; cs++)
696  {
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))
700  nom = std::max(nom, temp);
701  else
702  denom = std::max(denom, temp);
703  }
704  index = n*nb_bits_symb+nr;
705  extrinsic_data(index) = (nom-denom)-apriori_data(index);//extrinsic information
706  }
707  }
708 }
709 
710 void SISO::demodulator_logMAP(itpp::vec &extrinsic_data, const itpp::cvec &rec_sig, const itpp::vec &apriori_data)
712 {
713  int nb_symb = rec_sig.length();
714  int const_size = itpp::pow2i(nb_bits_symb);
715  double nom,denom,temp;
716  register int k,i,cs;
717  int index;
718  extrinsic_data.set_size(nb_bits_symb*nb_symb);
719  for (k=0; k<nb_symb; k++)
720  {
721  for (i=0; i<nb_bits_symb; i++)
722  {
723  nom = 0;
724  denom = 0;
725  for (cs=0; cs<const_size; cs++)
726  {
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))
730  nom += std::exp(temp);
731  else
732  denom += std::exp(temp);
733  }
734  index = k*nb_bits_symb+i;
735  extrinsic_data(index) = std::log(nom/denom)-apriori_data(index);//extrinsic information
736  }
737  }
738 }
739 
740 void SISO::demodulator_maxlogMAP(itpp::vec &extrinsic_data, const itpp::cvec &rec_sig, const itpp::vec &apriori_data)
742 {
743  int nb_symb = rec_sig.length();
744  int const_size = itpp::pow2i(nb_bits_symb);
745  double nom,denom,temp;
746  register int k,i,cs;
747  int index;
748  extrinsic_data.set_size(nb_bits_symb*nb_symb);
749  for (k=0; k<nb_symb; k++)
750  {
751  for (i=0; i<nb_bits_symb; i++)
752  {
753  nom = -INFINITY;
754  denom = -INFINITY;
755  for (cs=0; cs<const_size; cs++)
756  {
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))
760  nom = std::max(nom, temp);
761  else
762  denom = std::max(denom, temp);
763  }
764  index = k*nb_bits_symb+i;
765  extrinsic_data(index) = (nom-denom)-apriori_data(index);//extrinsic information
766  }
767  }
768 }
769 }//end namespace tr
SourceForge Logo

Generated on Sat Jul 6 2013 10:54:23 for IT++ by Doxygen 1.8.2