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
35namespace itpp
36{
37void 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
105void 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
120void 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
156void 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
189void 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
243void 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
349void 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
448void 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
557void 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
661void 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
710void 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
740void 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
Mat< Num_T > transpose() const
Matrix transpose.
Definition mat.h:1169
Mat< T > diag(const Vec< T > &v, const int K=0)
Create a diagonal matrix using vector v as its diagonal.
Definition matfunc.h:557
bool inv(const mat &X, mat &Y)
Inverse of real square matrix.
Definition inv.cpp:87
int pow2i(int x)
Calculate two to the power of x (2^x); x is integer.
Definition log_exp.h:53
vec exp(const vec &x)
Exp of the elements of a vector x.
Definition log_exp.h:155
T sum(const Vec< T > &v)
Sum of all elements in the vector.
Definition matfunc.h:59
void transpose(const Mat< T > &m, Mat< T > &out)
Transposition of the matrix m returning the transposed matrix in out.
Definition matfunc.h:308
T sum_sqr(const Vec< T > &v)
Sum of square of the elements in a vector.
Definition matfunc.h:116
T prod(const Vec< T > &v)
The product of all elements in the vector.
Definition matfunc.h:195
vec imag(const cvec &data)
Imaginary part of complex values.
ivec find(const bvec &invector)
Return a integer vector with indicies where bvec == 1.
Definition specmat.cpp:40
vec real(const cvec &data)
Real part of complex values.
vec sqr(const cvec &data)
Absolute square of elements.
Definition elem_math.cpp:36
cvec conj(const cvec &x)
Conjugate of complex value.
Definition elem_math.h:226
Mat< T > reshape(const Mat< T > &m, int rows, int cols)
Reshape the matrix into an rows*cols matrix.
Definition matfunc.h:822
itpp namespace
Definition itmex.h:37
template void eye(int, mat &)
Template instantiation of eye.
ITPP_EXPORT int bin2dec(const bvec &inbvec, bool msb_first=true)
Convert a bvec to decimal int with the first bit as MSB if msb_first == true.
vec to_vec(const Vec< T > &v)
Converts a Vec<T> to vec.
Definition converters.h:93
ITPP_EXPORT bvec dec2bin(int length, int index)
Convert a decimal int index to bvec using length bits in the representation.
Mat< Num_T > elem_div(const Mat< Num_T > &m1, const Mat< Num_T > &m2)
Element wise division of two matrices.
Definition mat.h:1688
Mat< Num_T > elem_mult(const Mat< Num_T > &m1, const Mat< Num_T > &m2)
Element wise multiplication of two matrices.
Definition mat.h:1582
bin abs(const bin &inbin)
absolute value of bin
Definition binary.h:174
Mat< Num_T > outer_product(const Vec< Num_T > &v1, const Vec< Num_T > &v2, bool hermitian=false)
Outer product of two vectors v1 and v2.
Definition vec.h:1021
Definitions for Soft Input Soft Output (SISO) modules class.
SourceForge Logo

Generated on Mon Jun 10 2024 11:49:22 for IT++ by Doxygen 1.9.8