59     result(0) = result(1) - l;
 
   63     result(1) = result(0) + l;
 
   69                               QLLR scaled_norm, 
int j, QLLRvec &p1,
 
   72   QLLR log_apriori_prob_const_point = 0;
 
   74   for (
int i = 0; i < 
k(j); i++) {
 
   75     log_apriori_prob_const_point +=
 
   76       ((
bitmap(j)(s, i) == 0) ? logP_apriori(b)(1) : logP_apriori(b)(0));
 
   81   for (
int i = 0; i < 
k(j); i++) {
 
   82     if (
bitmap(j)(s, i) == 0) {
 
   84                              + log_apriori_prob_const_point);
 
   88                              + log_apriori_prob_const_point);
 
   95                               const ivec &s, QLLR scaled_norm,
 
   96                               QLLRvec &p1, QLLRvec &p0)
 
   98   QLLR log_apriori_prob_const_point = 0;
 
  100   for (
int j = 0; j < 
nt; j++) {
 
  101     for (
int i = 0; i < 
k(j); i++) {
 
  102       log_apriori_prob_const_point +=
 
  103         ((
bitmap(j)(s[j], i) == 0) ? logP_apriori(b)(1) : logP_apriori(b)(0));
 
  109   for (
int j = 0; j < 
nt; j++) {
 
  110     for (
int i = 0; i < 
k(j); i++) {
 
  111       if (
bitmap(j)(s[j], i) == 0) {
 
  113                                + log_apriori_prob_const_point);
 
  117                                + log_apriori_prob_const_point);
 
  133     QLLR logsum0, logsum1;
 
  134     const QLLR *
const addrfirst = 
Qnorms._data();
 
  135     const QLLR *
const addrsemilast = addrfirst + (1 << (
nb - 1)), *
const addrlast = addrfirst + (1 << 
nb);
 
  137     for(
int bi = 3; bi < 
nb - 1 ; bi++) { 
 
  140       const int forhalfdiff = 1 << bi, fordiff = 2 * forhalfdiff, fordbldiff = 2 * fordiff;
 
  142       const QLLR *
const addr1 = addrfirst + forhalfdiff, *
const addr2 = addr1 + fordiff, *
const addr3 = addrlast - fordiff;
 
  143       while(Qptr < addr1) logsum0 = 
llrcalc.
jaclog(*(Qptr++), logsum0);
 
  144       while(Qptr < addr2) logsum1 = 
llrcalc.
jaclog(*(Qptr++), logsum1);
 
  145       const QLLR *addrdyn0, *addrdyn1;
 
  146       while(Qptr < addr3) {
 
  147         addrdyn0 = Qptr + fordiff;
 
  148         addrdyn1 = Qptr + fordbldiff;
 
  149         while(Qptr < addrdyn0) logsum0 = 
llrcalc.
jaclog(*(Qptr++), logsum0);
 
  150         while(Qptr < addrdyn1) logsum1 = 
llrcalc.
jaclog(*(Qptr++), logsum1);
 
  152       while(Qptr < addrlast) logsum0 = 
llrcalc.
jaclog(*(Qptr++), logsum0);
 
  153       llr[bi] = logsum0 - logsum1;
 
  159     while(Qptr < addrsemilast) logsum0 = 
llrcalc.
jaclog(*(Qptr++), logsum0);
 
  160     while(Qptr < addrlast) logsum1 = 
llrcalc.
jaclog(*(Qptr++), logsum1);
 
  161     llr[nb - 1] = logsum0 - logsum1;
 
  170     QLLR logmax0, logmax1;
 
  171     const QLLR *
const addrfirst = 
Qnorms._data();
 
  172     const QLLR *
const addrsemilast = addrfirst + (1 << (
nb - 1)), *
const addrlast = addrfirst + (1 << 
nb);
 
  174     for(
int bi = 3; bi < 
nb - 1; bi++) { 
 
  177       const int forhalfdiff = 1 << bi, fordiff = 2 * forhalfdiff, fordbldiff = 2 * fordiff;
 
  179       const QLLR *
const addr1 = addrfirst + forhalfdiff, *
const addr2 = addr1 + fordiff, *
const addr3 = addrlast - fordiff;
 
  180       for(; Qptr < addr1; Qptr++) logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  181       for(; Qptr < addr2; Qptr++) logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  182       const QLLR *addrdyn0, *addrdyn1;
 
  183       while(Qptr < addr3) {
 
  184         addrdyn0 = Qptr + fordiff;
 
  185         addrdyn1 = Qptr + fordbldiff;
 
  186         for(; Qptr < addrdyn0; Qptr++) logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  187         for(; Qptr < addrdyn1; Qptr++) logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  189       for(; Qptr < addrlast; Qptr++) logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  190       llr[bi] = logmax0 - logmax1;
 
  196     for(; Qptr < addrsemilast; Qptr++) logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  197     for(; Qptr < addrlast; Qptr++) logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  198     llr[nb - 1] = logmax0 - logmax1;
 
  200   else it_error(
"Improper soft demodulation method\n.");        
 
  205   using namespace itpp;
 
  206   QLLR logsum0 = -QLLR_MAX, logsum1 = -QLLR_MAX;
 
  207   const QLLR *
const addrfirst = 
Qnorms._data(), *
const addr3 = addrfirst + (1 << 
nb) - 1;
 
  208   const QLLR *Qptr = addrfirst;
 
  212   while(Qptr < addr3) {
 
  219   llr = logsum0 - logsum1;
 
  224   using namespace itpp;
 
  225   QLLR logsum0 = -QLLR_MAX, logsum1 = -QLLR_MAX;
 
  226   const QLLR *
const addrfirst = 
Qnorms._data(), *
const addr3 = addrfirst + (1 << 
nb) - 2;
 
  227   const QLLR *Qptr = addrfirst;
 
  235   while(Qptr < addr3) {
 
  247   llr = logsum0 - logsum1;
 
  252   using namespace itpp;
 
  253   QLLR logsum0 = -QLLR_MAX, logsum1 = -QLLR_MAX;
 
  254   const QLLR *
const addrfirst = 
Qnorms._data(), *
const addr3 = addrfirst + (1 << 
nb) - 4;
 
  255   const QLLR *Qptr = addrfirst;
 
  269   while(Qptr < addr3) {
 
  291   llr = logsum0 - logsum1;
 
  296   using namespace itpp;
 
  297   QLLR logmax0 = -QLLR_MAX, logmax1 = -QLLR_MAX;
 
  298   const QLLR *
const addrfirst = 
Qnorms._data(), *
const addr3 = addrfirst + (1 << 
nb) - 1;
 
  299   const QLLR *Qptr = addrfirst;
 
  300   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  302   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  304   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  306   while(Qptr < addr3) {
 
  307     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  309     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  311     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  313     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  316   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  317   maxllr = logmax0 - logmax1;
 
  322   using namespace itpp;
 
  323   QLLR logmax0 = -QLLR_MAX, logmax1 = -QLLR_MAX;
 
  324   const QLLR *
const addrfirst = 
Qnorms._data(), *
const addr3 = addrfirst + (1 << 
nb) - 2;
 
  325   const QLLR *Qptr = addrfirst;
 
  326   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  328   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  330   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  332   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  334   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  336   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  338   while(Qptr < addr3) {
 
  339     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  341     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  343     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  345     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  347     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  349     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  351     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  353     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  356   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  358   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  359   maxllr = logmax0 - logmax1;
 
  364   using namespace itpp;
 
  365   QLLR logmax0 = -QLLR_MAX, logmax1 = -QLLR_MAX;
 
  366   const QLLR *
const addrfirst = 
Qnorms._data(), *
const addr3 = addrfirst + (1 << 
nb) - 4;
 
  367   const QLLR *Qptr = addrfirst;
 
  368   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  370   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  372   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  374   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  376   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  378   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  380   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  382   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  384   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  386   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  388   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  390   logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  392   while(Qptr < addr3) {
 
  393     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  395     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  397     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  399     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  401     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  403     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  405     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  407     logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  409     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  411     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  413     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  415     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  417     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  419     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  421     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  423     logmax1 = *Qptr > logmax1 ? *Qptr : logmax1;
 
  426   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  428   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  430   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  432   logmax0 = *Qptr > logmax0 ? *Qptr : logmax0;
 
  433   maxllr = logmax0 - logmax1;
 
  440   for(
int i = 0; i < 
length(l); i++) {
 
  455   for(
int i = 0; i < 
nt; ++i) {
 
  456     it_assert(
M.length() == symbols.length(), 
"Modulator_NRD::get_symbols(): " 
  457               "The length of M vector is different than length of the symbols vector.");
 
  458     retvec(i) = symbols(i).
left(
M(i));
 
  466             "The number of input bits does not match.");
 
  468   out_symbols.set_size(
nt);
 
  471   for(
int i = 0; i < 
nt; ++i) {
 
  472     int symb = 
bin2dec(bits.mid(b, 
k(i)));
 
  481   modulate_bits(bits, result);
 
  488   using namespace itpp;
 
  489   it_assert(H_in.cols() == 
nt, 
"Number of Tx antennas is wrong.\n");
 
  490   it_assert(
sum(
k) < 32, 
"Number of total bits per transmission can not be larger than 32.\n");
 
  491   it_assert(
pow2i(
sum(
k)) == 
prod(
M), 
"Modulator must use exhaustive constellations, i.e., #bits=log2(#symbs).\n");
 
  497   hspacings.set_size(
nt);
 
  498   yspacings.set_size(
nt);
 
  502   vec startsymbvec(
nt);
 
  503   for(
int ci = 0; ci < 
nt; ci++) startsymbvec[ci] = symbols(ci)[0];
 
  504   itpp::vec Hx = H * startsymbvec;
 
  505   for(
int ci = 0, bcs = 0; ci < 
nt; bcs += 
k[ci++]) {
 
  506     for(
int bi = 0; bi < 
k[ci]; bi++) 
bpos2cpos[bcs + bi] = ci;
 
  508     for(
int si = 0; si < M[ci]; si++) gray2dec(ci)[si ^(si >> 1)] = si;
 
  509     yspacings(ci).set_size(
M[ci] - 1);
 
  510     hspacings(ci).set_size(
M[ci] - 1);
 
  511     for(
int si = 0; si < 
M[ci] - 1; si++) {
 
  512       double xspacing = symbols(ci)[
bits2symbols(ci)[(si + 1) ^((si + 1) >> 1)]];
 
  513       xspacing -= symbols(ci)[
bits2symbols(ci)[si ^(si >> 1)]];
 
  514       hspacings(ci)(si) = H.get_col(ci) * xspacing;
 
  518   unsigned bitstring = 0, ind = 0;
 
  519   hxnormupdate(Hx, bitstring, ind, 
nb - 1);
 
  526     const itpp::QLLRvec& llr_apr,
 
  530   using namespace itpp;
 
  533   it_assert_debug(H.rows() == y.length(), 
"The dimensions are not correct.\n");
 
  542   vec ytil = H.T() * y;
 
  543   vec startsymbvec(
nt);
 
  544   for(
int ci = 0; ci < 
nt; ci++) startsymbvec[ci] = symbols(ci)[0];
 
  545   double yx = 2*(ytil * startsymbvec);
 
  549   for(
int ci = 0; ci < 
nt; ci++)  
for(
int si = 0; si < 
M[ci] - 1; si++) {
 
  550       double xspacing = symbols(ci)[
bits2symbols(ci)[(si + 1) ^((si + 1) >> 1)]];
 
  551       xspacing -= symbols(ci)[
bits2symbols(ci)[si ^(si >> 1)]];
 
  552       yspacings(ci)[si] = 2*(ytil(ci) * xspacing);
 
  554   unsigned bitstring = 0, ind = 0;
 
  555   yxnormupdate(yx, lapr, bitstring, ind, 
nb - 1); 
 
  562     const QLLRvec &LLR_apriori,
 
  563     QLLRvec &LLR_aposteriori,
 
  568     it_assert(H.rows() >= H.cols(), 
"Modulator_NRD::demodulate_soft_bits():" 
  569               " ZF demodulation impossible for undetermined systems");
 
  572     mat inv_HtH = 
inv(Ht * H);
 
  573     vec shat = inv_HtH * Ht * y;
 
  574     vec h = 
ones(shat.size());
 
  575     for(
int i = 0; i < shat.size(); ++i) {
 
  577       double sigma_zf = 
std::sqrt(inv_HtH(i, i) * sigma2);
 
  581     demodulate_soft_bits(shat, h, 1.0, 
zeros_i(
sum(
k)), LLR_aposteriori);
 
  585     init_soft_demodulator(H, sigma2);
 
  586     demodulate_soft_bits(y, LLR_apriori, LLR_aposteriori, method);
 
  593     const QLLRvec &LLR_apriori,
 
  597   demodulate_soft_bits(y, H, sigma2, LLR_apriori, result, method);
 
  603     const QLLRvec &LLR_apriori,
 
  604     QLLRvec &LLR_aposteriori)
 
  607             "Modulator_NRD::demodulate_soft_bits(): Wrong sizes");
 
  609             "Modulator_NRD::demodulate_soft_bits(): Wrong sizes");
 
  612   LLR_aposteriori.set_size(LLR_apriori.size());
 
  615   double moo2s2 = -1.0 / (2.0 * sigma2);
 
  618   for(
int i = 0; i < 
nt; ++i) {
 
  619     QLLRvec bnum = -QLLR_MAX * 
ones_i(
k(i));
 
  620     QLLRvec bdenom = bnum;
 
  622     for(
int j = 0; j < 
M(i); ++j) {
 
  623       double norm2 = moo2s2 * 
sqr(y(i) - h(i) * symbols(i)(j));
 
  625       update_LLR(logP_apriori, j, scaled_norm, i, bnum, bdenom);
 
  627     LLR_aposteriori.set_subvector(b, bnum - bdenom);
 
  634         using namespace itpp;
 
  638                 unsigned oldi = 
gray2dec(col)[bitstring & (
M[col] - 1)];
 
  640                 unsigned newi = 
gray2dec(col)[bitstring & (
M[col] - 1)];
 
  641                 Hx += oldi > newi ? -hspacings(col)(newi) : hspacings(col)(oldi);
 
  645         hxnormupdate(Hx, bitstring, ind, bit - 1);
 
  647         bitstring ^= 1 << bit;
 
  649         Hx += oldi > newi ? -hspacings(col)(newi) : hspacings(col)(oldi);
 
  650         hxnormupdate(Hx, bitstring, ind, bit - 1);
 
  655   using namespace itpp;
 
  660     unsigned oldi = 
gray2dec(col)[bitstring & (
M[col] - 1)];
 
  662     unsigned newi = 
gray2dec(col)[bitstring & (
M[col] - 1)];
 
  663     yx += oldi > newi ? -yspacings(col)[newi] : yspacings(col)[oldi];
 
  669   yxnormupdate(yx, lapr, bitstring, ind, bit - 1);
 
  671   bitstring ^= 1 << bit;
 
  673   yx += oldi > newi ? -yspacings(col)[newi] : yspacings(col)[oldi];
 
  674   lapr += ((bitstring >> bit) & 1) ? -
llrapr[bit] : 
llrapr[bit];
 
  675   yxnormupdate(yx, lapr, bitstring, ind, bit - 1);
 
  681   os << 
"--- REAL MIMO (NRD) CHANNEL ---------" << std::endl;
 
  682   os << 
"Dimension (nt):           " << mod.
nt << std::endl;
 
  683   os << 
"Bits per dimension (k):   " << mod.
k << std::endl;
 
  684   os << 
"Symbols per dimension (M):" << mod.
M << std::endl;
 
  685   for(
int i = 0; i < mod.
nt; i++) {
 
  686     os << 
"Bitmap for dimension " << i << 
": " << mod.
bitmap(i) << std::endl;
 
  688     os << 
"Symbol coordinates for dimension " << i << 
": " << mod.
symbols(i).
left(mod.
M(i)) << std::endl;
 
  701   for(
int i = 0; i < 
nt; ++i) {
 
  702     it_assert(
M.length() == symbols.length(), 
"Modulator_NRD::get_symbols(): " 
  703               "The length of M vector is different than length of the symbols vector.");
 
  704     retvec(i) = symbols(i).
left(
M(i));
 
  712             "The number of input bits does not match.");
 
  714   out_symbols.set_size(
nt);
 
  717   for(
int i = 0; i < 
nt; ++i) {
 
  718     int symb = 
bin2dec(bits.mid(b, 
k(i)));
 
  727   modulate_bits(bits, result);
 
  733   using namespace itpp;
 
  735   it_assert_debug(
sum(
k) < 32, 
"Number of total bits per transmission can not be larger than 32.\n");
 
  742   hspacings.set_size(
nt);
 
  743   yspacings.set_size(
nt);
 
  747   cvec startsymbvec(
nt);
 
  748   for(
int ci = 0; ci < 
nt; ci++) startsymbvec[ci] = symbols(ci)[0];
 
  749   cvec Hx = H * startsymbvec;
 
  750   for(
int ci = 0, bcs = 0; ci < 
nt; bcs += 
k[ci++]) {
 
  751     for(
int bi = 0; bi < 
k[ci]; bi++) 
bpos2cpos[bcs + bi] = ci;
 
  753     for(
int si = 0; si < M[ci]; si++) gray2dec(ci)[si ^(si >> 1)] = si;
 
  754     yspacings(ci).set_size(
M[ci] - 1);
 
  755     hspacings(ci).set_size(
M[ci] - 1);
 
  756     for(
int si = 0; si < 
M[ci] - 1; si++) {
 
  757                  std::complex<double> xspacing = symbols(ci)[
bits2symbols(ci)[(si + 1) ^((si + 1) >> 1)]];
 
  758                  xspacing -= symbols(ci)[
bits2symbols(ci)[si ^(si >> 1)]];
 
  759                  hspacings(ci)(si) = H.get_col(ci) * xspacing;
 
  763   unsigned bitstring = 0, ind = 0;
 
  764   hxnormupdate(Hx, bitstring, ind, 
nb - 1);
 
  769     const itpp::QLLRvec& llr_apr,
 
  773   using namespace itpp;
 
  776   it_assert_debug(H.rows() == y.length(), 
"The dimensions are not correct.\n");
 
  784   cvec ytil = 
conj(H.H() * y);
 
  785   cvec startsymbvec(
nt);
 
  786   for(
int ci = 0; ci < 
nt; ci++) startsymbvec[ci] = symbols(ci)[0];
 
  787   double yx = 2*(ytil * startsymbvec).
real();
 
  790   for(
int ci = 0; ci < 
nt; ci++)  
for(
int si = 0; si < 
M[ci] - 1; si++) {
 
  791                   std::complex<double> xspacing = symbols(ci)[
bits2symbols(ci)[(si + 1) ^((si + 1) >> 1)]];
 
  792                   xspacing -= symbols(ci)[
bits2symbols(ci)[si ^(si >> 1)]];
 
  793                   yspacings(ci)[si] = 2*(ytil[ci] * xspacing).
real();
 
  795   unsigned bitstring = 0, ind = 0;
 
  796   yxnormupdate(yx, lapr, bitstring, ind, 
nb - 1); 
 
  803     const QLLRvec &LLR_apriori,
 
  804     QLLRvec &LLR_aposteriori,
 
  809               it_assert(H.rows() >= H.cols(), 
"Modulator_NCD::demodulate_soft_bits():" 
  810               " ZF demodulation impossible for undetermined systems");
 
  813     cmat inv_HhtH = 
inv(Hht * H);
 
  814     cvec shat = inv_HhtH * Hht * y;
 
  815     cvec h = 
ones_c(shat.size());
 
  816     for(
int i = 0; i < shat.size(); ++i) {
 
  821     demodulate_soft_bits(shat, h, 1.0, 
zeros_i(
sum(
k)), LLR_aposteriori);
 
  825     init_soft_demodulator(H, sigma2);
 
  826     demodulate_soft_bits(y, LLR_apriori, LLR_aposteriori, method);
 
  833     const QLLRvec &LLR_apriori,
 
  837   demodulate_soft_bits(y, H, sigma2, LLR_apriori, result, method);
 
  844     const QLLRvec &LLR_apriori,
 
  845     QLLRvec &LLR_aposteriori)
 
  848             "Modulator_NCD::demodulate_soft_bits(): Wrong sizes");
 
  850             "Modulator_NCD::demodulate_soft_bits(): Wrong sizes");
 
  853   LLR_aposteriori.set_size(LLR_apriori.size());
 
  856   double moos2 = -1.0 / sigma2;
 
  859   for(
int i = 0; i < 
nt; ++i) {
 
  860     QLLRvec bnum = -QLLR_MAX * 
ones_i(
k(i));
 
  861     QLLRvec bdenom = -QLLR_MAX * 
ones_i(
k(i));
 
  863     for(
int j = 0; j < 
M(i); ++j) {
 
  864       double norm2 = moos2 * 
sqr(y(i) - h(i) * symbols(i)(j));
 
  866       update_LLR(logP_apriori, j, scaled_norm, i, bnum, bdenom);
 
  868     LLR_aposteriori.set_subvector(b, bnum - bdenom);
 
  874 void Modulator_NCD::hxnormupdate(itpp::cvec& Hx, 
unsigned& bitstring, 
unsigned& ind, 
unsigned bit)
 
  876   using namespace itpp;
 
  880           unsigned oldi = 
gray2dec(col)[bitstring & (
M[col] - 1)];
 
  882     unsigned newi = 
gray2dec(col)[bitstring & (
M[col] - 1)];
 
  883     Hx += oldi > newi ? -hspacings(col)(newi) : hspacings(col)(oldi);
 
  887   hxnormupdate(Hx, bitstring, ind, bit - 1);
 
  889   bitstring ^= 1 << bit;
 
  891   Hx += oldi > newi ? -hspacings(col)(newi) : hspacings(col)(oldi);
 
  892   hxnormupdate(Hx, bitstring, ind, bit - 1);
 
  895 void Modulator_NCD::yxnormupdate(
double& yx, itpp::QLLR& lapr, 
unsigned& bitstring, 
unsigned& ind, 
unsigned bit)
 
  897   using namespace itpp;
 
  904     unsigned oldi = 
gray2dec(col)[bitstring & (
M[col] - 1)];
 
  906     unsigned newi = 
gray2dec(col)[bitstring & (
M[col] - 1)];
 
  907     yx += oldi > newi ? -yspacings(col)[newi] : yspacings(col)[oldi];
 
  913   yxnormupdate(yx, lapr, bitstring, ind, bit - 1);
 
  915   bitstring ^= 1 << bit;
 
  917   yx += oldi > newi ? -yspacings(col)[newi] : yspacings(col)[oldi];
 
  918   lapr += ((bitstring >> bit) & 1) ? -
llrapr[bit] : 
llrapr[bit];
 
  919   yxnormupdate(yx, lapr, bitstring, ind, bit - 1);
 
  925   os << 
"--- COMPLEX MIMO (NCD) CHANNEL --------" << std::endl;
 
  926   os << 
"Dimension (nt):           " << mod.
nt << std::endl;
 
  927   os << 
"Bits per dimension (k):   " << mod.
k << std::endl;
 
  928   os << 
"Symbols per dimension (M):" << mod.
M << std::endl;
 
  929   for(
int i = 0; i < mod.
nt; i++) {
 
  930     os << 
"Bitmap for dimension " << i << 
": " 
  931        << mod.
bitmap(i) << std::endl;
 
  932     os << 
"Symbol coordinates for dimension " << i << 
": " 
  953   set_M(
nt, Mary_temp);
 
  963   symbols.set_size(
nt);
 
  965   spacing.set_size(
nt);
 
  967   for(
int i = 0; i < 
nt; i++) {
 
  970               "ND_UPAM::set_M(): M is not a power of 2.");
 
  972     symbols(i).set_size(
M(i) + 1);
 
  975     double average_energy = (
M(i) * 
M(i) - 1) / 3.0;
 
  976     double scaling_factor = 
std::sqrt(average_energy);
 
  978     for(
int j = 0; j < 
M(i); ++j) {
 
  979       symbols(i)(j) = ((
M(i) - 1) - j * 2) / scaling_factor;
 
  985     symbols(i)(
M(i)) = 0.0;
 
  987     spacing(i) = 2.0 / scaling_factor;
 
  991 int ND_UPAM::sphere_search_SE(
const vec &y_in, 
const mat &H,
 
  992                               const imat &zrange, 
double r, ivec &zhat)
 
 1003   mat R = 
chol(H.transpose() * H);
 
 1006   vec y = Q.transpose() * y_in;
 
 1007   mat Vi = Ri.transpose();
 
 1012   double bestdist = r * r;
 
 1015   mat E = 
zeros(n, n);
 
 1016   for(
int i = 0; i < n; i++) {    
 
 1017     for(
int j = 0; j < n; j++) {
 
 1018       E(i * n + n - 1) += y(j) * Vi(j + n * i);
 
 1024   z(n - 1) = 
floor_i(0.5 + E(n * n - 1));
 
 1025   z(n - 1) = 
std::max(z(n - 1), zrange(n - 1, 0));
 
 1026   z(n - 1) = 
std::min(z(n - 1), zrange(n - 1, 1));
 
 1027   double p = (E(n * n - 1) - z(n - 1)) / Vi(n * n - 1);
 
 1029   step(n - 1) = sign_nozero_i(p);
 
 1035     double newdist = dist(k) + p * p;
 
 1037     if((newdist < bestdist) && (k != 0)) {
 
 1038       for(
int i = 0; i < 
k; i++) {
 
 1039         E(k - 1 + i * n) = E(k + i * n) - p * Vi(k + i * n);
 
 1044       z(k) = 
floor_i(0.5 + E(k + k * n));
 
 1045       z(k) = 
std::max(z(k), zrange(k, 0));
 
 1046       z(k) = 
std::min(z(k), zrange(k, 1));
 
 1047       p = (E(k + k * n) - z(k)) / Vi(k + k * n);
 
 1049       step(k) = sign_nozero_i(p);
 
 1053         if(newdist < bestdist) {
 
 1058         else if(k == n - 1) {
 
 1067         if((z(k) < zrange(k, 0)) || (z(k) > zrange(k, 1))) {
 
 1068           step(k) = (-step(k) - sign_nozero_i(step(k)));
 
 1072         if((z(k) >= zrange(k, 0)) && (z(k) <= zrange(k, 1))) {
 
 1077       p = (E(k + k * n) - z(k)) / Vi(k + k * n);
 
 1078       step(k) = (-step(k) - sign_nozero_i(step(k)));
 
 1088                              double rmax, 
double stepup,
 
 1089                              QLLRvec &detected_bits)
 
 1092             "ND_UPAM::sphere_decoding(): dimension mismatch");
 
 1094             "ND_UPAM::sphere_decoding(): dimension mismatch");
 
 1095   it_assert(rstart > 0, 
"ND_UPAM::sphere_decoding(): radius error");
 
 1096   it_assert(rmax > rstart, 
"ND_UPAM::sphere_decoding(): radius error");
 
 1101   mat Htemp(H.rows(), H.cols());
 
 1102   for(
int i = 0; i < H.cols(); i++) {
 
 1103     Htemp.set_col(i, H.get_col(i)*spacing(i));
 
 1104     ytemp += Htemp.get_col(i) * 0.5 * (
M(i) - 1.0);
 
 1108   for(
int i = 0; i < 
nt; i++) {
 
 1110     crange(i, 1) = 
M(i) - 1;
 
 1117     status = sphere_search_SE(ytemp, Htemp, crange, r, s);
 
 1120       detected_bits.set_size(
sum(k));
 
 1122       for(
int j = 0; j < 
nt; j++) {
 
 1123         for(
int i = 0; i < 
k(j); i++) {
 
 1124           if(
bitmap(j)((
M(j) - 1 - s[j]), i) == 0) {
 
 1125             detected_bits(b) = 1000;
 
 1128             detected_bits(b) = -1000;
 
 1161   set_M(
nt, Mary_temp);
 
 1172   symbols.set_size(
nt);
 
 1175   for(
int i = 0; i < 
nt; ++i) {
 
 1178               "ND_UQAM::set_M(): M is not a power of 2");
 
 1181     it_assert(L(i)*L(i) == 
M(i), 
"ND_UQAM: constellation M must be square");
 
 1183     symbols(i).set_size(
M(i) + 1);
 
 1186     double average_energy = (
M(i) - 1) * 2.0 / 3.0;
 
 1187     double scaling_factor = 
std::sqrt(average_energy);
 
 1190     for(
int j1 = 0; j1 < L(i); ++j1) {
 
 1191       for(
int j2 = 0; j2 < L(i); ++j2) {
 
 1192         symbols(i)(j1 * L(i) + j2) =
 
 1193           std::complex<double>(((L(i) - 1) - j2 * 2.0) / scaling_factor,
 
 1194                                ((L(i) - 1) - j1 * 2.0) / scaling_factor);
 
 1195         bitmap(i).set_row(j1 * L(i) + j2, 
concat(gray_code.get_row(j1),
 
 1196                           gray_code.get_row(j2)));
 
 1204     symbols(i)(
M(i)) = 0.0;
 
 1210   it_assert(
nt > nth, 
"ND_UQAM::set_constellation_points(): Number of input to change is out of the size");
 
 1211   it_assert(inConstellation.size() == in_bit2symbols.size(),
 
 1212             "ND_UQAM::set_constellation_points(): Number of constellation and bits2symbols does not match");
 
 1214             "ND_UQAM::set_constellation_points(): Number of symbols needs to be even and non-zero");
 
 1216   symbols(nth).replace_mid(0, inConstellation);
 
 1220   for(
int m = 0; m < 
M(nth); ++m) {
 
 1226   symbols(nth)(
M(nth)) = 0.0;
 
 1243   set_M(
nt, Mary_temp);
 
 1253   symbols.set_size(
nt);
 
 1256   for(
int i = 0; i < 
nt; ++i) {
 
 1259               "ND_UPSK::set_M(): M is not a power of 2");
 
 1261     symbols(i).set_size(
M(i) + 1);
 
 1265     double delta = 2.0 * 
pi / 
M(i);
 
 1266     double epsilon = delta / 10000.0;
 
 1268     for(
int j = 0; j < 
M(i); ++j) {
 
 1269       std::complex<double> symb
 
 1270       = std::complex<double>(std::polar(1.0, delta * j));
 
 1273         symbols(i)(j) = std::complex<double>(0.0, 
std::imag(symb));
 
 1276         symbols(i)(j) = std::complex<double>(
std::real(symb), 0.0);
 
 1279         symbols(i)(j) = symb;
 
 1287     symbols(i)(
M(i)) = 0.0;