IT++ Logo
stc.cpp
Go to the documentation of this file.
1
29#include <itpp/comm/stc.h>
30
31namespace itpp
32{
33
34void STC::Hassibi_block_code(void)
35/* This function generates the A and B matrices needed for Space-Time block codes
36 * generation following Hassibi's approach:
37 * S = sum_{q=1}^symb_block (A_q alpha_q + jB_q beta_q),
38 * where s_q = alpha_q+jbeta_q is the symbol after modulation
39 * each A_q and B_q matrix has dimension TxM
40 * different A_q and B_q matrices are stacked one below the other, e.g.
41 * [A_1;A_2;...;A_Q]
42
43 * input: code_name - code name whose generator matrices are to be generated
44 * const_size - constellation size (used in Damen code)
45 * outputs: symb_block - number of symbols per block
46 * A, B - generator matrices
47 * inputs/outputs: for some codes these are inputs for others they are
48 * predefined, so they are outputs only
49 * em_antennas - number of emission antenna
50 * channel_uses - channel uses
51 */
52{
53 if (code_name==Code_Names::V_BLAST_MxN)//classical V-BLAST
54 {
55 it_assert(channel_uses > 0, "Channel uses should be strictly positive");
56 it_assert(em_antenna > 0, "Number of emission antenna should be strictly positive");
57 symb_block = channel_uses*em_antenna;//number of symbols/block
58 A.set_size(symb_block*channel_uses, em_antenna);
59 A.zeros();
60 itpp::mat temp(channel_uses, em_antenna);
61 temp.zeros();
62 register int tau,m;
63 for (tau=0; tau<channel_uses; tau++)
64 {
65 for (m=0; m<em_antenna; m++)
66 {
67 temp(tau,m) = 1;
68 A.set_submatrix(symb_block*tau+channel_uses*m, 0, itpp::to_cmat(temp));
69 temp(tau,m) = 0;
70 }
71 }
72 B = A;
73 }
74 else if (code_name == Code_Names::imp_V_BLAST_MxN)//improved V-BLAST (code (31) in Hassibi's paper)
75 {
76 it_assert(em_antenna > 0, "Number of emission antenna should be strictly positive");
77 it_assert(channel_uses == em_antenna, "Channel uses and the number of emission antenna must be equal");
78 symb_block = channel_uses*em_antenna;//number of symbols/block
79 std::complex<double> j(0,1);
80 itpp::cmat D = itpp::diag(exp(j*(2*itpp::pi/em_antenna)*
81 itpp::linspace(0, em_antenna-1, em_antenna)));
82 itpp::mat P = itpp::diag(itpp::ones(em_antenna-1), -1);
83 P(0,em_antenna-1) = 1;
84 A.set_size(symb_block*channel_uses, em_antenna);
85 A.zeros();
86 register int k,l;
87 for (k=0; k<channel_uses; k++)
88 {
89 for (l=0; l<em_antenna; l++)
90 {
91 A.set_submatrix(symb_block*k+l*channel_uses, 0,
92 diag_pow(D, k)*itpp::to_cmat(mat_pow(P, l))/
93 std::sqrt(double(em_antenna)));
94 }
95 }
96 B = A;
97 }
98 else if (code_name==Code_Names::Alamouti_2xN)//Alamouti's orthogonal code
99 {
100 em_antenna = 2;//emission antenna
101 channel_uses = 2;//channel uses
102 symb_block = 2;//number of symbols/block
103
104 A = "1 0;"
105 "0 1;"
106 "0 1;"
107 "-1 0";//A_1; A_2
108 B = "1 0;"
109 "0 -1;"
110 "0 1;"
111 "1 0";//B_1; B_2
112 }
113 else if (code_name==Code_Names::Switched_Alamouti_4xN)
114 {
115 em_antenna = 4;//emission antenna
116 channel_uses = 4;//channel uses
117 symb_block = 4;//number of symbols/block
118
119 A = "1 0 0 0;"
120 "0 1 0 0;"
121 "0 0 0 0;"
122 "0 0 0 0;"
123 "0 1 0 0;"
124 "-1 0 0 0;"
125 "0 0 0 0;"
126 "0 0 0 0;"
127 "0 0 0 0;"
128 "0 0 0 0;"
129 "0 0 1 0;"
130 "0 0 0 1;"
131 "0 0 0 0;"
132 "0 0 0 0;"
133 "0 0 0 1;"
134 "0 0 -1 0";//A_1; A_2; A_3; A_4
135 A *= std::sqrt(2.0);//normalization
136 B = "1 0 0 0;"
137 "0 -1 0 0;"
138 "0 0 0 0;"
139 "0 0 0 0;"
140 "0 1 0 0;"
141 "1 0 0 0;"
142 "0 0 0 0;"
143 "0 0 0 0;"
144 "0 0 0 0;"
145 "0 0 0 0;"
146 "0 0 1 0;"
147 "0 0 0 -1;"
148 "0 0 0 0;"
149 "0 0 0 0;"
150 "0 0 0 1;"
151 "0 0 1 0";//B_1; B_2; B_3; B_4
152 B *= std::sqrt(2.0);
153 }
154 else if (code_name==Code_Names::Double_Alamouti_4xN)
155 {
156 em_antenna = 4;//emission antenna
157 channel_uses = 2;//channel uses
158 symb_block = 4;//number of symbols/block
159
160 A = "1 0 0 0;"
161 "0 1 0 0;"
162 "0 0 1 0;"
163 "0 0 0 1;"
164 "0 1 0 0;"
165 "-1 0 0 0;"
166 "0 0 0 1;"
167 "0 0 -1 0";//A_1; A_2; A_3; A_4
168 B = "1 0 0 0;"
169 "0 -1 0 0;"
170 "0 0 1 0;"
171 "0 0 0 -1;"
172 "0 1 0 0;"
173 "1 0 0 0;"
174 "0 0 0 1;"
175 "0 0 1 0";//B_1; B_2; B_3; B_4
176 }
177 else if (code_name== Code_Names::Jafarkhani_4xN)//Jafarkhani's quasi-orthogonal code
178 {
179 em_antenna = 4;//emission antenna
180 channel_uses = 4;//channel uses
181 symb_block = 4;//number of symbols/block
182
183 A = "1 0 0 0;"
184 "0 1 0 0;"
185 "0 0 1 0;"
186 "0 0 0 1;"
187 "0 1 0 0;"
188 "-1 0 0 0;"
189 "0 0 0 1;"
190 "0 0 -1 0;"
191 "0 0 1 0;"
192 "0 0 0 1;"
193 "-1 0 0 0;"
194 "0 -1 0 0;"
195 "0 0 0 1;"
196 "0 0 -1 0;"
197 "0 -1 0 0;"
198 "1 0 0 0";//A_1; A_2; A_3; A_4
199 B = "1 0 0 0;"
200 "0 -1 0 0;"
201 "0 0 -1 0;"
202 "0 0 0 1;"
203 "0 1 0 0;"
204 "1 0 0 0;"
205 "0 0 0 -1;"
206 "0 0 -1 0;"
207 "0 0 1 0;"
208 "0 0 0 -1;"
209 "1 0 0 0;"
210 "0 -1 0 0;"
211 "0 0 0 1;"
212 "0 0 1 0;"
213 "0 1 0 0;"
214 "1 0 0 0";//B_1; B_2; B_3; B_4
215 }
216 else if (code_name== Code_Names::Golden_2x2)//Golden code as proposed by Belfiore
217 {
218 em_antenna = 2;//emission antenna
219 channel_uses = 2;//channel uses
220 symb_block = 4;//number of symbols/block
221
222 std::complex<double> theta((1+std::sqrt(5.0))/2,0);
223 std::complex<double> theta_b((1-std::sqrt(5.0))/2,0);
224 std::complex<double> j(0,1);
225 std::complex<double> one(1,0);
226 std::complex<double> alpha = one+j*(one-theta);
227 std::complex<double> alpha_b = one+j*(one-theta_b);
228 std::complex<double> gamma = j;
229 A.set_size(8,2);
230 A(0,0) = alpha/std::sqrt(5.0);
231 A(0,1) = 0;
232 A(1,0) = 0;
233 A(1,1) = alpha_b/std::sqrt(5.0);//A_1
234 A(2,0) = alpha*theta/std::sqrt(5.0);
235 A(2,1) = 0;
236 A(3,0) = 0;
237 A(3,1) = alpha_b*theta_b/std::sqrt(5.0);//A_2
238 A(4,0) = 0;
239 A(4,1) = gamma*alpha_b/std::sqrt(5.0);
240 A(5,0) = alpha/std::sqrt(5.0);
241 A(5,1) = 0;//A_3
242 A(6,0) = 0;
243 A(6,1) = gamma*alpha_b*theta_b/std::sqrt(5.0);
244 A(7,0) = alpha*theta/std::sqrt(5.0);
245 A(7,1) = 0;//A_4
246 B = A;
247 }
248 else if (code_name== Code_Names::Damen_2x2)//ST code based on number theory as proposed by Damen
249 {
250 em_antenna = 2;//emission antenna
251 channel_uses = 2;//channel uses
252 symb_block = 4;//number of symbols/block
253
254 double lambda;
255 if (const_size==4)
256 lambda = 0.5;
257 else if (const_size==16)
258 lambda = 0.521;
259 else if (const_size>=256)
260 lambda = itpp::pi/4;
261 else
262 {
263 lambda = itpp::pi/4;
264 std::cout << "STC::LDcode: Warning! For " << string_from_code_name(code_name) <<
265 " and const. size " << const_size << ", lambda has the "
266 "value " << lambda << std::endl;
267 }
268 std::complex<double> j(0,1);
269 std::complex<double> phi = std::exp(j*lambda);
270 std::complex<double> theta = std::exp(j*(lambda/2));
271 A.set_size(8, 2);
272 A(0,0) = 1/std::sqrt(2.0);
273 A(0,1) = 0;
274 A(1,0) = 0;
275 A(1,1) = 1/std::sqrt(2.0);//A_1
276 A(2,0) = phi/std::sqrt(2.0);
277 A(2,1) = 0;
278 A(3,0) = 0;
279 A(3,1) = -phi/std::sqrt(2.0);//A_2
280 A(4,0) = 0;
281 A(4,1) = theta/std::sqrt(2.0);
282 A(5,0) = theta/std::sqrt(2.0);
283 A(5,1) = 0;//A_3
284 A(6,0) = 0;
285 A(6,1) = -theta*phi/std::sqrt(2.0);
286 A(7,0) = theta*phi/std::sqrt(2.0);
287 A(7,1) = 0;//A_4
288 B = A;
289 }
290 else if (code_name== Code_Names::ortho34_3xN)//rate 3/4 orthogonal code (mutual information 5.13 bits/channel use at rho=20 dB)
291 {
292 em_antenna = 3;//emission antenna
293 channel_uses = 4;//channel uses
294 symb_block = 3;//number of symbols/block
295
296 A = "1 0 0;"
297 "0 1 0;"
298 "0 0 1;"
299 "0 0 0;"
300 "0 1 0;"
301 "-1 0 0;"
302 "0 0 0;"
303 "0 0 1;"
304 "0 0 1;"
305 "0 0 0;"
306 "-1 0 0;"
307 "0 -1 0";//A_1; A_2; A_3
308 A /= std::sqrt(double(4)/double(3));
309 B = "1 0 0;"
310 "0 -1 0;"
311 "0 0 -1;"
312 "0 0 0;"
313 "0 1 0;"
314 "1 0 0;"
315 "0 0 0;"
316 "0 0 -1;"
317 "0 0 1;"
318 "0 0 0;"
319 "1 0 0;"
320 "0 1 0";//B_1; B_2; B_3
321 B /= std::sqrt(double(4)/double(3));
322 }
323 else if (code_name== Code_Names::LD36_3xN)//(36) LD code with mutual info. 6.25bits/channel use at rho=20dB
324 {
325 em_antenna = 3;//emission antenna
326 channel_uses = 4;//channel uses
327 symb_block = 4;//number of symbols/block
328
329 A.set_size(16, 3);
330 A(0,0) = 1;
331 A(0,1) = 0;
332 A(0,2) = 0;
333 A(1,0) = 1;
334 A(1,1) = 1;
335 A(1,2) = 0;
336 A(2,0) = 0;
337 A(2,1) = 0;
338 A(2,2) = 1;
339 A(3,0) = 0;
340 A(3,1) = 0;
341 A(3,2) = 0;//A_1
342 A(4,0) = 0;
343 A(4,1) = 1/std::sqrt(2.0);
344 A(4,2) = 0;
345 A(5,0) = -1/std::sqrt(2.0);
346 A(5,1) = 0;
347 A(5,2) = -1/std::sqrt(2.0);
348 A(6,0) = 0;
349 A(6,1) = 1/std::sqrt(2.0);
350 A(6,2) = 0;
351 A(7,0) = 1/std::sqrt(2.0);
352 A(7,1) = 0;
353 A(7,2) = -1/std::sqrt(2.0);//A_2
354 A(8,0) = 1;
355 A(8,1) = 0;
356 A(8,2) = 0;
357 A(9,0) = 0;
358 A(9,1) = 0;
359 A(9,2) = 0;
360 A(10,0) = 0;
361 A(10,1) = 0;
362 A(10,2) = -1;
363 A(11,0) = 0;
364 A(11,1) = -1;
365 A(11,2) = 0;//A_3
366 A(12,0) = 0;
367 A(12,1) = -1/std::sqrt(2.0);
368 A(12,2) = 0;
369 A(13,0) = 1/std::sqrt(2.0);
370 A(13,1) = 0;
371 A(13,2) = -1/std::sqrt(2.0);
372 A(14,0) = 0;
373 A(14,1) = 1/std::sqrt(2.0);
374 A(14,2) = 0;
375 A(15,0) = -1/std::sqrt(2.0);
376 A(15,1) = 0;
377 A(15,2) = -1/std::sqrt(2.0);//A_4
378 B.set_size(16, 3);
379 B(0,0) = 0;
380 B(0,1) = -1/std::sqrt(2.0);
381 B(0,2) = 0;
382 B(1,0) = -1/std::sqrt(2.0);
383 B(1,1) = 0;
384 B(1,2) = 1/std::sqrt(2.0);
385 B(2,0) = 0;
386 B(2,1) = 1/std::sqrt(2.0);
387 B(2,2) = 0;
388 B(3,0) = 1/std::sqrt(2.0);
389 B(3,1) = 0;
390 B(3,2) = 1/std::sqrt(2.0);//B_1
391 B(4,0) = 1/std::sqrt(2.0);
392 B(4,1) = double(-1)/double(2);
393 B(4,2) = 0;
394 B(5,0) = double(-1)/double(2);
395 B(5,1) = -1/std::sqrt(2.0);
396 B(5,2) = double(-1)/double(2);
397 B(6,0) = 0;
398 B(6,1) = double(-1)/double(2);
399 B(6,2) = 1/std::sqrt(2.0);
400 B(7,0) = double(1)/double(2);
401 B(7,1) = 0;
402 B(7,2) = double(-1)/double(2);//B_2
403 B(8,0) = 1/std::sqrt(2.0);
404 B(8,1) = double(1)/double(2);
405 B(8,2) = 0;
406 B(9,0) = double(1)/double(2);
407 B(9,1) = -1/std::sqrt(2.0);
408 B(9,2) = double(1)/double(2);
409 B(10,0) = 0;
410 B(10,1) = double(1)/double(2);
411 B(10,2) = 1/std::sqrt(2.0);
412 B(11,0) = double(-1)/double(2);
413 B(11,1) = 0;
414 B(11,2) = double(1)/double(2);//B_3
415 B(12,0) = 1;
416 B(12,1) = 0;
417 B(12,2) = 0;
418 B(13,0) = 0;
419 B(13,1) = 0;
420 B(13,2) = 0;
421 B(14,0) = 0;
422 B(14,1) = 0;
423 B(14,2) = -1;
424 B(15,0) = 0;
425 B(15,1) = 1;
426 B(15,2) = 0;//B_4
427 }
428 else if (code_name== Code_Names::LD37_3xN)//(37) LD code 3-antenna LD code obtained from the symetrical concatenation of 3 2-antenna orthogonal design
429 {
430 em_antenna = 3;//emission antenna
431 channel_uses = 6;//channel uses
432 symb_block = 6;//number of symbols/block
433
434 A = "1 0 0;"
435 "0 1 0;"
436 "0 0 0;"
437 "0 0 0;"
438 "0 0 0;"
439 "0 0 0;"
440 "0 1 0;"
441 "-1 0 0;"
442 "0 0 0;"
443 "0 0 0;"
444 "0 0 0;"
445 "0 0 0;"
446 "0 0 0;"
447 "0 0 0;"
448 "0 1 0;"
449 "0 0 1;"
450 "0 0 0;"
451 "0 0 0;"
452 "0 0 0;"
453 "0 0 0;"
454 "0 0 1;"
455 "0 -1 0;"
456 "0 0 0;"
457 "0 0 0;"
458 "0 0 0;"
459 "0 0 0;"
460 "0 0 0;"
461 "0 0 0;"
462 "1 0 0;"
463 "0 0 1;"
464 "0 0 0;"
465 "0 0 0;"
466 "0 0 0;"
467 "0 0 0;"
468 "0 0 1;"
469 "-1 0 0";//A_1; A_2; A_3; A_4; A_5; A_6
470 A *= std::sqrt(double(3)/double(2));
471 B = "1 0 0;"
472 "0 -1 0;"
473 "0 0 0;"
474 "0 0 0;"
475 "0 0 0;"
476 "0 0 0;"
477 "0 1 0;"
478 "1 0 0;"
479 "0 0 0;"
480 "0 0 0;"
481 "0 0 0;"
482 "0 0 0;"
483 "0 0 0;"
484 "0 0 0;"
485 "0 1 0;"
486 "0 0 -1;"
487 "0 0 0;"
488 "0 0 0;"
489 "0 0 0;"
490 "0 0 0;"
491 "0 0 1;"
492 "0 1 0;"
493 "0 0 0;"
494 "0 0 0;"
495 "0 0 0;"
496 "0 0 0;"
497 "0 0 0;"
498 "0 0 0;"
499 "1 0 0;"
500 "0 0 -1;"
501 "0 0 0;"
502 "0 0 0;"
503 "0 0 0;"
504 "0 0 0;"
505 "0 0 1;"
506 "1 0 0";//B_1; B_2; B_3; B_4; B_5; B_6
507 B *= std::sqrt(double(3)/double(2));
508 }
509 else if (code_name== Code_Names::LD39_3xN)
510 {
511 em_antenna = 3;//emission antenna
512 channel_uses = 6;//channel uses
513 symb_block = 6;//number of symbols/block
514
515 A.set_size(36, 3);
516 A(0,0) = 1/std::sqrt(2.0);
517 A(0,1) = 0;
518 A(0,2) = 0;
519 A(1,0) = 0;
520 A(1,1) = 1/std::sqrt(2.0);
521 A(1,2) = 0;
522 A(2,0) = 0;
523 A(2,1) = 1/std::sqrt(2.0);
524 A(2,2) = 0;
525 A(3,0) = 0;
526 A(3,1) = 0;
527 A(3,2) = 1/std::sqrt(2.0);
528 A(4,0) = 1/std::sqrt(2.0);
529 A(4,1) = 0;
530 A(4,2) = 0;
531 A(5,0) = 0;
532 A(5,1) = 0;
533 A(5,2) = 1/std::sqrt(2.0);//A_1
534 A(6,0) = 0;
535 A(6,1) = 1/std::sqrt(2.0);
536 A(6,2) = 0;
537 A(7,0) = -1/std::sqrt(2.0);
538 A(7,1) = 0;
539 A(7,2) = 0;
540 A(8,0) = 0;
541 A(8,1) = 0;
542 A(8,2) = 1/std::sqrt(2.0);
543 A(9,0) = 0;
544 A(9,1) = -1/std::sqrt(2.0);
545 A(9,2) = 0;
546 A(10,0) = 0;
547 A(10,1) = 0;
548 A(10,2) = 1/std::sqrt(2.0);
549 A(11,0) = -1/std::sqrt(2.0);
550 A(11,1) = 0;
551 A(11,2) = 0;//A_2
552 A(12,0) = 1/std::sqrt(2.0);
553 A(12,1) = 0;
554 A(12,2) = 0;
555 A(13,0) = 0;
556 A(13,1) = 1/std::sqrt(2.0);
557 A(13,2) = 0;
558 A(14,0) = 0;
559 A(14,1) = -1/(2*std::sqrt(2.0));
560 A(14,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
561 A(15,0) = 0;
562 A(15,1) = std::sqrt(3.0)/(2*std::sqrt(2.0));
563 A(15,2) = -1/(2*std::sqrt(2.0));
564 A(16,0) = -1/(2*std::sqrt(2.0));
565 A(16,1) = 0;
566 A(16,2) = std::sqrt(3.0)/(2*std::sqrt(2.0));
567 A(17,0) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
568 A(17,1) = 0;
569 A(17,2) = -1/(2*std::sqrt(2.0));//A_3
570 A(18,0) = 0;
571 A(18,1) = 1/std::sqrt(2.0);
572 A(18,2) = 0;
573 A(19,0) = -1/std::sqrt(2.0);
574 A(19,1) = 0;
575 A(19,2) = 0;
576 A(20,0) = 0;
577 A(20,1) = std::sqrt(3.0)/(2*std::sqrt(2.0));
578 A(20,2) = -1/(2*std::sqrt(2.0));
579 A(21,0) = 0;
580 A(21,1) = 1/(2*std::sqrt(2.0));
581 A(21,2) = std::sqrt(3.0)/(2*std::sqrt(2.0));
582 A(22,0) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
583 A(22,1) = 0;
584 A(22,2) = -1/(2*std::sqrt(2.0));
585 A(23,0) = 1/(2*std::sqrt(2.0));
586 A(23,1) = 0;
587 A(23,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0));//A_4
588 A(24,0) = 1/std::sqrt(2.0);
589 A(24,1) = 0;
590 A(24,2) = 0;
591 A(25,0) = 0;
592 A(25,1) = 1/std::sqrt(2.0);
593 A(25,2) = 0;
594 A(26,0) = 0;
595 A(26,1) = -1/(2*std::sqrt(2.0));
596 A(26,2) = std::sqrt(3.0)/(2*std::sqrt(2.0));
597 A(27,0) = 0;
598 A(27,1) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
599 A(27,2) = -1/(2*std::sqrt(2.0));
600 A(28,0) = -1/(2*std::sqrt(2.0));
601 A(28,1) = 0;
602 A(28,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
603 A(29,0) = std::sqrt(3.0)/(2*std::sqrt(2.0));
604 A(29,1) = 0;
605 A(29,2) = -1/(2*std::sqrt(2.0));//A_5
606 A(30,0) = 0;
607 A(30,1) = 1/std::sqrt(2.0);
608 A(30,2) = 0;
609 A(31,0) = -1/std::sqrt(2.0);
610 A(31,1) = 0;
611 A(31,2) = 0;
612 A(32,0) = 0;
613 A(32,1) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
614 A(32,2) = -1/(2*std::sqrt(2.0));
615 A(33,0) = 0;
616 A(33,1) = 1/(2*std::sqrt(2.0));
617 A(33,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
618 A(34,0) = std::sqrt(3.0)/(2*std::sqrt(2.0));
619 A(34,1) = 0;
620 A(34,2) = -1/(2*std::sqrt(2.0));
621 A(35,0) = 1/(2*std::sqrt(2.0));
622 A(35,1) = 0;
623 A(35,2) = std::sqrt(3.0)/(2*std::sqrt(2.0));//A_6
624 B.set_size(36, 3);
625 B(0,0) = 1/std::sqrt(2.0);
626 B(0,1) = 0;
627 B(0,2) = 0;
628 B(1,0) = 0;
629 B(1,1) = -1/std::sqrt(2.0);
630 B(1,2) = 0;
631 B(2,0) = 0;
632 B(2,1) = 1/std::sqrt(2.0);
633 B(2,2) = 0;
634 B(3,0) = 0;
635 B(3,1) = 0;
636 B(3,2) = -1/std::sqrt(2.0);
637 B(4,0) = 1/std::sqrt(2.0);
638 B(4,1) = 0;
639 B(4,2) = 0;
640 B(5,0) = 0;
641 B(5,1) = 0;
642 B(5,2) = -1/std::sqrt(2.0);//B_1
643 B(6,0) = 0;
644 B(6,1) = 1/std::sqrt(2.0);
645 B(6,2) = 0;
646 B(7,0) = 1/std::sqrt(2.0);
647 B(7,1) = 0;
648 B(7,2) = 0;
649 B(8,0) = 0;
650 B(8,1) = 0;
651 B(8,2) = 1/std::sqrt(2.0);
652 B(9,0) = 0;
653 B(9,1) = 1/std::sqrt(2.0);
654 B(9,2) = 0;
655 B(10,0) = 0;
656 B(10,1) = 0;
657 B(10,2) = 1/std::sqrt(2.0);
658 B(11,0) = 1/std::sqrt(2.0);
659 B(11,1) = 0;
660 B(11,2) = 0;//B_2
661 B(12,0) = 1/std::sqrt(2.0);
662 B(12,1) = 0;
663 B(12,2) = 0;
664 B(13,0) = 0;
665 B(13,1) = -1/std::sqrt(2.0);
666 B(13,2) = 0;
667 B(14,0) = 0;
668 B(14,1) = -1/(2*std::sqrt(2.0));
669 B(14,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
670 B(15,0) = 0;
671 B(15,1) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
672 B(15,2) = 1/(2*std::sqrt(2.0));
673 B(16,0) = -1/(2*std::sqrt(2.0));
674 B(16,1) = 0;
675 B(16,2) = std::sqrt(3.0)/(2*std::sqrt(2.0));
676 B(17,0) = std::sqrt(3.0)/(2*std::sqrt(2.0));
677 B(17,1) = 0;
678 B(17,2) = 1/(2*std::sqrt(2.0));//B_3
679 B(18,0) = 0;
680 B(18,1) = 1/std::sqrt(2.0);
681 B(18,2) = 0;
682 B(19,0) = 1/std::sqrt(2.0);
683 B(19,1) = 0;
684 B(19,2) = 0;
685 B(20,0) = 0;
686 B(20,1) = std::sqrt(3.0)/(2*std::sqrt(2.0));
687 B(20,2) = -1/(2*std::sqrt(2.0));
688 B(21,0) = 0;
689 B(21,1) = -1/(2*std::sqrt(2.0));
690 B(21,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
691 B(22,0) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
692 B(22,1) = 0;
693 B(22,2) = -1/(2*std::sqrt(2.0));
694 B(23,0) = -1/(2*std::sqrt(2.0));
695 B(23,1) = 0;
696 B(23,2) = std::sqrt(3.0)/(2*std::sqrt(2.0));//B_4
697 B(24,0) = 1/std::sqrt(2.0);
698 B(24,1) = 0;
699 B(24,2) = 0;
700 B(25,0) = 0;
701 B(25,1) = -1/std::sqrt(2.0);
702 B(25,2) = 0;
703 B(26,0) = 0;
704 B(26,1) = -1/(2*std::sqrt(2.0));
705 B(26,2) = std::sqrt(3.0)/(2*std::sqrt(2.0));
706 B(27,0) = 0;
707 B(27,1) = std::sqrt(3.0)/(2*std::sqrt(2.0));
708 B(27,2) = 1/(2*std::sqrt(2.0));
709 B(28,0) = -1/(2*std::sqrt(2.0));
710 B(28,1) = 0;
711 B(28,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
712 B(29,0) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
713 B(29,1) = 0;
714 B(29,2) = 1/(2*std::sqrt(2.0));//B_5
715 B(30,0) = 0;
716 B(30,1) = 1/std::sqrt(2.0);
717 B(30,2) = 0;
718 B(31,0) = 1/std::sqrt(2.0);
719 B(31,1) = 0;
720 B(31,2) = 0;
721 B(32,0) = 0;
722 B(32,1) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
723 B(32,2) = -1/(2*std::sqrt(2.0));
724 B(33,0) = 0;
725 B(33,1) = -1/(2*std::sqrt(2.0));
726 B(33,2) = std::sqrt(3.0)/(2*std::sqrt(2.0));
727 B(34,0) = std::sqrt(3.0)/(2*std::sqrt(2.0));
728 B(34,1) = 0;
729 B(34,2) = -1/(2*std::sqrt(2.0));
730 B(35,0) = -1/(2*std::sqrt(2.0));
731 B(35,1) = 0;
732 B(35,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0));//B_6
733 }
734 else
735 {
736 it_assert(false, "Unknown code name.");
737 }
738}
739
740itpp::cmat STC::encode(const itpp::cvec &symb)
741//LD code generation (symb_block symbols go to an channel_uses x em_antennas matrix) following Hassibi's approach
742{
743 int nb_subblocks = symb.length()/symb_block;
744 int tx_duration = channel_uses*nb_subblocks;
745 itpp::cmat S(tx_duration,em_antenna);
746 itpp::cmat temp(channel_uses,em_antenna);
747 std::complex<double> j(0,1);
748 register int ns,k;
749 for (ns=0; ns<nb_subblocks; ns++)//encode block by block (symb_block symbols)
750 {
751 temp.zeros();
752 for (k=0; k<symb_block; k++)//sum over all symb_block matrices
753 {
754 temp += (A(k*channel_uses,(k+1)*channel_uses-1,0,em_antenna-1)*
755 static_cast< std::complex<double> >(symb(k+ns*symb_block).real())+
756 j*B(k*channel_uses,(k+1)*channel_uses-1,0,em_antenna-1)*
757 static_cast< std::complex<double> >(symb(k+ns*symb_block).imag()));
758 }
759 S.set_submatrix(ns*channel_uses, 0, temp);
760 }
761 return S;
762}
763
764itpp::cmat STC::diag_pow(const itpp::cmat &in_mat, double in_exp)
765//first input should be a diagonal square matrix with complex elements
766{
767 register int n;
768 int dim = in_mat.rows();
769 itpp::cmat out_mat(dim,dim);
770 out_mat.zeros();
771 for (n=0; n<dim; n++)
772 {
773 out_mat(n,n) = std::pow(in_mat(n,n), in_exp);
774 }
775 return out_mat;
776}
777
778itpp::mat STC::mat_pow(const itpp::mat &in_mat, int in_exp)
779//square matrix power of integer exponent
780{
781 if (in_exp==0)
782 {
783 return itpp::eye(in_mat.rows());
784 }
785 itpp::mat out = in_mat;
786 int abs_in_exp = std::abs(in_exp);
787 register int n;
788 for (n=1; n<abs_in_exp; n++)
789 {
790 out *= in_mat;
791 }
792 return (in_exp>0)?out:itpp::inv(out);
793}
794
795}
General array class.
Definition array.h:105
int length() const
Returns the number of data elements in the array object.
Definition array.h:157
itpp::cmat encode(const itpp::cvec &symb)
Encodes input symbols according to the specified ST code.
Definition stc.cpp:740
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
#define it_assert(t, s)
Abort if t is not true.
Definition itassert.h:94
bool inv(const mat &X, mat &Y)
Inverse of real square matrix.
Definition inv.cpp:87
vec exp(const vec &x)
Exp of the elements of a vector x.
Definition log_exp.h:155
double gamma(double x)
Deprecated gamma function - please use tgamma() instead.
Definition elem_math.cpp:79
vec linspace(double from, double to, int points)
linspace (works in the same way as the MATLAB version)
Definition specmat.cpp:106
ITPP_EXPORT vec ones(int size)
A float vector of ones.
itpp namespace
Definition itmex.h:37
cmat to_cmat(const Mat< T > &m)
Converts a Mat<T> to cmat.
Definition converters.h:232
template void eye(int, mat &)
Template instantiation of eye.
const double pi
Constant Pi.
Definition misc.h:103
Definitions for Space Time Codes (STC) class.

Generated on Tue Aug 17 2021 10:59:15 for IT++ by Doxygen 1.9.8