34void STC::Hassibi_block_code(
void)
53 if (code_name==Code_Names::V_BLAST_MxN)
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;
58 A.set_size(symb_block*channel_uses, em_antenna);
60 itpp::mat temp(channel_uses, em_antenna);
63 for (tau=0; tau<channel_uses; tau++)
65 for (m=0; m<em_antenna; m++)
68 A.set_submatrix(symb_block*tau+channel_uses*m, 0,
itpp::to_cmat(temp));
74 else if (code_name == Code_Names::imp_V_BLAST_MxN)
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;
79 std::complex<double> j(0,1);
83 P(0,em_antenna-1) = 1;
84 A.set_size(symb_block*channel_uses, em_antenna);
87 for (k=0; k<channel_uses; k++)
89 for (l=0; l<em_antenna; l++)
91 A.set_submatrix(symb_block*k+l*channel_uses, 0,
93 std::sqrt(
double(em_antenna)));
98 else if (code_name==Code_Names::Alamouti_2xN)
113 else if (code_name==Code_Names::Switched_Alamouti_4xN)
154 else if (code_name==Code_Names::Double_Alamouti_4xN)
177 else if (code_name== Code_Names::Jafarkhani_4xN)
216 else if (code_name== Code_Names::Golden_2x2)
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;
230 A(0,0) = alpha/std::sqrt(5.0);
233 A(1,1) = alpha_b/std::sqrt(5.0);
234 A(2,0) = alpha*theta/std::sqrt(5.0);
237 A(3,1) = alpha_b*theta_b/std::sqrt(5.0);
239 A(4,1) =
gamma*alpha_b/std::sqrt(5.0);
240 A(5,0) = alpha/std::sqrt(5.0);
243 A(6,1) =
gamma*alpha_b*theta_b/std::sqrt(5.0);
244 A(7,0) = alpha*theta/std::sqrt(5.0);
248 else if (code_name== Code_Names::Damen_2x2)
257 else if (const_size==16)
259 else if (const_size>=256)
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;
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));
272 A(0,0) = 1/std::sqrt(2.0);
275 A(1,1) = 1/std::sqrt(2.0);
276 A(2,0) = phi/std::sqrt(2.0);
279 A(3,1) = -phi/std::sqrt(2.0);
281 A(4,1) = theta/std::sqrt(2.0);
282 A(5,0) = theta/std::sqrt(2.0);
285 A(6,1) = -theta*phi/std::sqrt(2.0);
286 A(7,0) = theta*phi/std::sqrt(2.0);
290 else if (code_name== Code_Names::ortho34_3xN)
308 A /= std::sqrt(
double(4)/
double(3));
321 B /= std::sqrt(
double(4)/
double(3));
323 else if (code_name== Code_Names::LD36_3xN)
343 A(4,1) = 1/std::sqrt(2.0);
345 A(5,0) = -1/std::sqrt(2.0);
347 A(5,2) = -1/std::sqrt(2.0);
349 A(6,1) = 1/std::sqrt(2.0);
351 A(7,0) = 1/std::sqrt(2.0);
353 A(7,2) = -1/std::sqrt(2.0);
367 A(12,1) = -1/std::sqrt(2.0);
369 A(13,0) = 1/std::sqrt(2.0);
371 A(13,2) = -1/std::sqrt(2.0);
373 A(14,1) = 1/std::sqrt(2.0);
375 A(15,0) = -1/std::sqrt(2.0);
377 A(15,2) = -1/std::sqrt(2.0);
380 B(0,1) = -1/std::sqrt(2.0);
382 B(1,0) = -1/std::sqrt(2.0);
384 B(1,2) = 1/std::sqrt(2.0);
386 B(2,1) = 1/std::sqrt(2.0);
388 B(3,0) = 1/std::sqrt(2.0);
390 B(3,2) = 1/std::sqrt(2.0);
391 B(4,0) = 1/std::sqrt(2.0);
392 B(4,1) = double(-1)/double(2);
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);
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);
402 B(7,2) = double(-1)/double(2);
403 B(8,0) = 1/std::sqrt(2.0);
404 B(8,1) = double(1)/double(2);
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);
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);
414 B(11,2) = double(1)/double(2);
428 else if (code_name== Code_Names::LD37_3xN)
470 A *= std::sqrt(
double(3)/
double(2));
507 B *= std::sqrt(
double(3)/
double(2));
509 else if (code_name== Code_Names::LD39_3xN)
516 A(0,0) = 1/std::sqrt(2.0);
520 A(1,1) = 1/std::sqrt(2.0);
523 A(2,1) = 1/std::sqrt(2.0);
527 A(3,2) = 1/std::sqrt(2.0);
528 A(4,0) = 1/std::sqrt(2.0);
533 A(5,2) = 1/std::sqrt(2.0);
535 A(6,1) = 1/std::sqrt(2.0);
537 A(7,0) = -1/std::sqrt(2.0);
542 A(8,2) = 1/std::sqrt(2.0);
544 A(9,1) = -1/std::sqrt(2.0);
548 A(10,2) = 1/std::sqrt(2.0);
549 A(11,0) = -1/std::sqrt(2.0);
552 A(12,0) = 1/std::sqrt(2.0);
556 A(13,1) = 1/std::sqrt(2.0);
559 A(14,1) = -1/(2*std::sqrt(2.0));
560 A(14,2) = -std::sqrt(3.0)/(2*std::sqrt(2.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));
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));
569 A(17,2) = -1/(2*std::sqrt(2.0));
571 A(18,1) = 1/std::sqrt(2.0);
573 A(19,0) = -1/std::sqrt(2.0);
577 A(20,1) = std::sqrt(3.0)/(2*std::sqrt(2.0));
578 A(20,2) = -1/(2*std::sqrt(2.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));
584 A(22,2) = -1/(2*std::sqrt(2.0));
585 A(23,0) = 1/(2*std::sqrt(2.0));
587 A(23,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
588 A(24,0) = 1/std::sqrt(2.0);
592 A(25,1) = 1/std::sqrt(2.0);
595 A(26,1) = -1/(2*std::sqrt(2.0));
596 A(26,2) = std::sqrt(3.0)/(2*std::sqrt(2.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));
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));
605 A(29,2) = -1/(2*std::sqrt(2.0));
607 A(30,1) = 1/std::sqrt(2.0);
609 A(31,0) = -1/std::sqrt(2.0);
613 A(32,1) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
614 A(32,2) = -1/(2*std::sqrt(2.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));
620 A(34,2) = -1/(2*std::sqrt(2.0));
621 A(35,0) = 1/(2*std::sqrt(2.0));
623 A(35,2) = std::sqrt(3.0)/(2*std::sqrt(2.0));
625 B(0,0) = 1/std::sqrt(2.0);
629 B(1,1) = -1/std::sqrt(2.0);
632 B(2,1) = 1/std::sqrt(2.0);
636 B(3,2) = -1/std::sqrt(2.0);
637 B(4,0) = 1/std::sqrt(2.0);
642 B(5,2) = -1/std::sqrt(2.0);
644 B(6,1) = 1/std::sqrt(2.0);
646 B(7,0) = 1/std::sqrt(2.0);
651 B(8,2) = 1/std::sqrt(2.0);
653 B(9,1) = 1/std::sqrt(2.0);
657 B(10,2) = 1/std::sqrt(2.0);
658 B(11,0) = 1/std::sqrt(2.0);
661 B(12,0) = 1/std::sqrt(2.0);
665 B(13,1) = -1/std::sqrt(2.0);
668 B(14,1) = -1/(2*std::sqrt(2.0));
669 B(14,2) = -std::sqrt(3.0)/(2*std::sqrt(2.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));
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));
678 B(17,2) = 1/(2*std::sqrt(2.0));
680 B(18,1) = 1/std::sqrt(2.0);
682 B(19,0) = 1/std::sqrt(2.0);
686 B(20,1) = std::sqrt(3.0)/(2*std::sqrt(2.0));
687 B(20,2) = -1/(2*std::sqrt(2.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));
693 B(22,2) = -1/(2*std::sqrt(2.0));
694 B(23,0) = -1/(2*std::sqrt(2.0));
696 B(23,2) = std::sqrt(3.0)/(2*std::sqrt(2.0));
697 B(24,0) = 1/std::sqrt(2.0);
701 B(25,1) = -1/std::sqrt(2.0);
704 B(26,1) = -1/(2*std::sqrt(2.0));
705 B(26,2) = std::sqrt(3.0)/(2*std::sqrt(2.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));
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));
714 B(29,2) = 1/(2*std::sqrt(2.0));
716 B(30,1) = 1/std::sqrt(2.0);
718 B(31,0) = 1/std::sqrt(2.0);
722 B(32,1) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
723 B(32,2) = -1/(2*std::sqrt(2.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));
729 B(34,2) = -1/(2*std::sqrt(2.0));
730 B(35,0) = -1/(2*std::sqrt(2.0));
732 B(35,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0));
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);
749 for (ns=0; ns<nb_subblocks; ns++)
752 for (k=0; k<symb_block; k++)
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()));
759 S.set_submatrix(ns*channel_uses, 0, temp);
764itpp::cmat STC::diag_pow(
const itpp::cmat &in_mat,
double in_exp)
768 int dim = in_mat.rows();
769 itpp::cmat out_mat(dim,dim);
771 for (n=0; n<dim; n++)
773 out_mat(n,n) = std::pow(in_mat(n,n), in_exp);
778itpp::mat STC::mat_pow(
const itpp::mat &in_mat,
int in_exp)
785 itpp::mat out = in_mat;
788 for (n=1; n<abs_in_exp; n++)
itpp::cmat encode(const itpp::cvec &symb)
Encodes input symbols according to the specified ST code.
Mat< T > diag(const Vec< T > &v, const int K=0)
Create a diagonal matrix using vector v as its diagonal.
#define it_assert(t, s)
Abort if t is not true.
bool inv(const mat &X, mat &Y)
Inverse of real square matrix.
vec exp(const vec &x)
Exp of the elements of a vector x.
double gamma(double x)
Deprecated gamma function - please use tgamma() instead.
vec linspace(double from, double to, int points)
linspace (works in the same way as the MATLAB version)
ITPP_EXPORT vec ones(int size)
A float vector of ones.
cmat to_cmat(const Mat< T > &m)
Converts a Mat<T> to cmat.
template void eye(int, mat &)
Template instantiation of eye.
const double pi
Constant Pi.
int abs(const itpp::bin &inbin)
absolute value of bin
Definitions for Space Time Codes (STC) class.