IT++ Logo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
modulator.h
Go to the documentation of this file.
1 
29 #ifndef MODULATOR_H
30 #define MODULATOR_H
31 
32 #include <itpp/base/mat.h>
34 #include <itpp/base/math/log_exp.h>
35 #include <itpp/base/converters.h>
36 #include <itpp/base/math/min_max.h>
37 
38 
39 namespace itpp
40 {
41 
49 };
50 
73 template <typename T>
74 class Modulator
75 {
76 public:
78  Modulator();
80  Modulator(const Vec<T>& symbols, const ivec& bits2symbols);
82  virtual ~Modulator() {}
83 
85  virtual void set(const Vec<T>& symbols, const ivec& bits2symbols);
86 
88  virtual int bits_per_symbol() const { return k; }
90  virtual Vec<T> get_symbols() const { return symbols; }
108  virtual ivec get_bits2symbols() const { return bits2symbols; }
109 
111  virtual void modulate(const ivec& symbolnumbers, Vec<T>& output) const;
113  virtual Vec<T> modulate(const ivec& symbolnumbers) const;
114 
116  virtual void demodulate(const Vec<T>& signal, ivec& output) const;
118  virtual ivec demodulate(const Vec<T>& signal) const;
119 
121  virtual void modulate_bits(const bvec& bits, Vec<T>& output) const;
123  virtual Vec<T> modulate_bits(const bvec& bits) const;
124 
126  virtual void demodulate_bits(const Vec<T>& signal, bvec& bits) const;
128  virtual bvec demodulate_bits(const Vec<T>& signal) const;
129 
169  virtual void demodulate_soft_bits(const Vec<T>& rx_symbols, double N0,
170  vec& soft_bits,
171  Soft_Method method = LOGMAP) const;
173  virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols, double N0,
174  Soft_Method method = LOGMAP) const;
175 
214  virtual void demodulate_soft_bits(const Vec<T>& rx_symbols,
215  const Vec<T>& channel,
216  double N0, vec& soft_bits,
217  Soft_Method method = LOGMAP) const;
219  virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols,
220  const Vec<T>& channel,
221  double N0,
222  Soft_Method method = LOGMAP) const;
223 
224 protected:
228  int k;
230  int M;
239  imat S0;
242  imat S1;
243 
246 };
247 
248 
249 // ----------------------------------------------------------------------
250 // Type definitions of Modulator_1D and Modulator_2D
251 // ----------------------------------------------------------------------
252 
258 
264 
265 
266 // ----------------------------------------------------------------------
267 // Implementation of templated Modulator members
268 // ----------------------------------------------------------------------
269 
270 template<typename T>
272  setup_done(false), k(0), M(0), bitmap(""), bits2symbols(""), symbols(""),
273  S0(""), S1("") {}
274 
275 template<typename T>
276 Modulator<T>::Modulator(const Vec<T> &symbols, const ivec &bits2symbols)
277 {
278  set(symbols, bits2symbols);
279 }
280 
281 template<typename T>
282 void Modulator<T>::set(const Vec<T> &in_symbols, const ivec &in_bits2symbols)
283 {
284  it_assert(in_symbols.size() == in_bits2symbols.size(),
285  "Modulator<T>::set(): Number of symbols and bits2symbols does not match");
286  it_assert(is_even(in_symbols.size()) && (in_symbols.size() > 0),
287  "Modulator<T>::set(): Number of symbols needs to be even and non-zero");
288  it_assert((max(in_bits2symbols) == in_bits2symbols.size() - 1)
289  && (min(in_bits2symbols) == 0), "Modulator<T>::set(): Improper bits2symbol vector");
290  symbols = in_symbols;
291  bits2symbols = in_bits2symbols;
292  M = bits2symbols.size();
293  k = levels2bits(M);
294  bitmap.set_size(M, k);
295  for (int m = 0; m < M; m++) {
296  bitmap.set_row(bits2symbols(m), dec2bin(k, m));
297  }
298  calculate_softbit_matrices();
299  setup_done = true;
300 }
301 
302 
303 template<typename T>
304 void Modulator<T>::modulate(const ivec &symbolnumbers, Vec<T>& output) const
305 {
306  it_assert_debug(setup_done, "Modulator<T>::modulate(): Modulator not ready.");
307  output.set_size(symbolnumbers.length());
308  for (int i = 0; i < symbolnumbers.length(); i++)
309  output(i) = symbols(symbolnumbers(i));
310 }
311 
312 template<typename T>
313 Vec<T> Modulator<T>::modulate(const ivec &symbolnumbers) const
314 {
315  Vec<T> output(symbolnumbers.length());
316  modulate(symbolnumbers, output);
317  return output;
318 }
319 
320 
321 template<typename T>
322 void Modulator<T>::demodulate(const Vec<T> &signal, ivec& output) const
323 {
324  it_assert_debug(setup_done, "Modulator<T>::demodulate(): Modulator not ready.");
325  double dist, mindist;
326  int closest;
327  output.set_size(signal.size());
328 
329  for (int i = 0; i < signal.size(); i++) {
330  mindist = std::abs(symbols(0) - signal(i));
331  closest = 0;
332  for (int j = 1; j < M; j++) {
333  dist = std::abs(symbols(j) - signal(i));
334  if (dist < mindist) {
335  mindist = dist;
336  closest = j;
337  }
338  }
339  output(i) = closest;
340  }
341 }
342 
343 template<typename T>
344 ivec Modulator<T>::demodulate(const Vec<T>& signal) const
345 {
346  ivec output(signal.length());
347  demodulate(signal, output);
348  return output;
349 }
350 
351 
352 template<typename T>
353 void Modulator<T>::modulate_bits(const bvec &bits, Vec<T> &output) const
354 {
355  it_assert_debug(setup_done, "Modulator<T>::modulate_bits(): Modulator not ready.");
356  // Check if some bits have to be cut and print warning message in such
357  // case.
358  if (bits.length() % k) {
359  it_warning("Modulator<T>::modulate_bits(): The number of input bits is not a multiple of k (number of bits per symbol). Remainder bits are not modulated.");
360  }
361  int no_symbols = bits.length() / k;
362  output.set_size(no_symbols);
363  for (int i = 0; i < no_symbols; i++) {
364  output(i) = symbols(bits2symbols(bin2dec(bits.mid(i * k, k))));
365  }
366 }
367 
368 template<typename T>
369 Vec<T> Modulator<T>::modulate_bits(const bvec &bits) const
370 {
371  Vec<T> output;
372  modulate_bits(bits, output);
373  return output;
374 }
375 
376 template<typename T>
377 void Modulator<T>::demodulate_bits(const Vec<T> &signal, bvec &bits) const
378 {
379  it_assert_debug(setup_done, "Modulator<T>::demodulate_bist(): Modulator not ready.");
380  double dist, mindist;
381  int closest;
382  bits.set_size(k*signal.size());
383 
384  for (int i = 0; i < signal.size(); i++) {
385  mindist = std::abs(symbols(0) - signal(i));
386  closest = 0;
387  for (int j = 1; j < M; j++) {
388  dist = std::abs(symbols(j) - signal(i));
389  if (dist < mindist) {
390  mindist = dist;
391  closest = j;
392  }
393  }
394  bits.replace_mid(i*k, bitmap.get_row(closest));
395  }
396 }
397 
398 template<typename T>
399 bvec Modulator<T>::demodulate_bits(const Vec<T> &signal) const
400 {
401  bvec bits;
402  demodulate_bits(signal, bits);
403  return bits;
404 }
405 
406 
407 template<typename T>
408 void Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols, double N0,
409  vec &soft_bits,
410  Soft_Method method) const
411 {
412  it_assert_debug(setup_done, "Modulator<T>::demodulate_soft_bits(): Modulator not ready.");
413  double P0, P1, d0min, d1min, temp;
414  vec metric(M);
415 
416  soft_bits.set_size(k * rx_symbols.size());
417 
418  if (method == LOGMAP) {
419  for (int l = 0; l < rx_symbols.size(); l++) {
420  for (int j = 0; j < M; j++) {
421  metric(j) = std::exp(-sqr(rx_symbols(l) - symbols(j)) / N0);
422  }
423  for (int i = 0; i < k; i++) {
424  P0 = P1 = 0;
425  for (int j = 0; j < (M >> 1); j++) {
426  P0 += metric(S0(i, j));
427  P1 += metric(S1(i, j));
428  }
429  soft_bits(l*k + i) = trunc_log(P0) - trunc_log(P1);
430  }
431  }
432  }
433  else { // method == APPROX
434  for (int l = 0; l < rx_symbols.size(); l++) {
435  for (int j = 0; j < M; j++) {
436  metric(j) = sqr(rx_symbols(l) - symbols(j));
437  }
438  for (int i = 0; i < k; i++) {
439  d0min = d1min = std::numeric_limits<double>::max();
440  for (int j = 0; j < (M >> 1); j++) {
441  temp = metric(S0(i, j));
442  if (temp < d0min) { d0min = temp; }
443  temp = metric(S1(i, j));
444  if (temp < d1min) { d1min = temp; }
445  }
446  soft_bits(l*k + i) = (-d0min + d1min) / N0;
447  }
448  }
449  }
450 }
451 
452 template<typename T>
454  double N0,
455  Soft_Method method) const
456 {
457  vec output;
458  demodulate_soft_bits(rx_symbols, N0, output, method);
459  return output;
460 }
461 
462 template<typename T>
464  const Vec<T> &channel, double N0,
465  vec &soft_bits,
466  Soft_Method method) const
467 {
468  it_assert_debug(setup_done, "Modulator_2D::demodulate_soft_bits(): Modulator not ready.");
469  double P0, P1, d0min, d1min, temp;
470  vec metric(M);
471 
472  soft_bits.set_size(k * rx_symbols.size());
473 
474  if (method == LOGMAP) {
475  for (int l = 0; l < rx_symbols.size(); l++) {
476  for (int j = 0; j < M; j++) {
477  metric(j) = std::exp(-sqr(rx_symbols(l) - channel(l) * symbols(j))
478  / N0);
479  }
480  for (int i = 0; i < k; i++) {
481  P0 = P1 = 0;
482  for (int j = 0; j < (M >> 1); j++) {
483  P0 += metric(S0(i, j));
484  P1 += metric(S1(i, j));
485  }
486  soft_bits(l*k + i) = trunc_log(P0) - trunc_log(P1);
487  }
488  }
489  }
490  else { // method == APPROX
491  for (int l = 0; l < rx_symbols.size(); l++) {
492  for (int j = 0; j < M; j++) {
493  metric(j) = sqr(rx_symbols(l) - channel(l) * symbols(j));
494  }
495  for (int i = 0; i < k; i++) {
496  d0min = d1min = std::numeric_limits<double>::max();
497  for (int j = 0; j < (M >> 1); j++) {
498  temp = metric(S0(i, j));
499  if (temp < d0min) { d0min = temp; }
500  temp = metric(S1(i, j));
501  if (temp < d1min) { d1min = temp; }
502  }
503  soft_bits(l*k + i) = (-d0min + d1min) / N0;
504  }
505  }
506  }
507 }
508 
509 template<typename T>
511  const Vec<T> &channel,
512  double N0,
513  Soft_Method method) const
514 {
515  vec output;
516  demodulate_soft_bits(rx_symbols, channel, N0, output, method);
517  return output;
518 }
519 
520 template<typename T>
522 {
523  int count0, count1;
524 
525  // Allocate storage space for the result matrices:
526  S0.set_size(k, M >> 1, false);
527  S1.set_size(k, M >> 1, false);
528 
529  for (int i = 0; i < k; i++) {
530  count0 = 0;
531  count1 = 0;
532  for (int j = 0; j < M; j++) {
533  if (bitmap(j, i) == bin(0)) {
534  S0(i, count0++) = j;
535  }
536  else {
537  S1(i, count1++) = j;
538  }
539  }
540  }
541 }
542 
543 
544 
545 // ----------------------------------------------------------------------
546 // QAM : Modulator_2D
547 // ----------------------------------------------------------------------
548 
569 class QAM : public Modulator<std::complex<double> >
570 {
571 public:
573  QAM() {}
575  QAM(int M) { set_M(M); }
577  virtual ~QAM() { }
579  void set_M(int M);
580 
582  void demodulate_bits(const cvec& signal, bvec& bits) const;
584  bvec demodulate_bits(const cvec& signal) const;
585 
586 protected:
588  int L;
591 };
592 
593 
594 // ----------------------------------------------------------------------
595 // PSK : Modulator<std::complex<double> >
596 // ----------------------------------------------------------------------
597 
618 class PSK : public Modulator<std::complex<double> >
619 {
620 public:
622  PSK() {}
624  PSK(int M) { set_M(M); }
626  virtual ~PSK() { }
628  void set_M(int M);
629 
631  void demodulate_bits(const cvec& signal, bvec& bits) const;
633  bvec demodulate_bits(const cvec& signal) const;
634 };
635 
636 
637 // ----------------------------------------------------------------------
638 // QPSK : PSK : Modulator<std::complex<double> >
639 // ----------------------------------------------------------------------
640 
660 class QPSK : public PSK
661 {
662 public:
664  QPSK(): PSK(4) {}
666  virtual ~QPSK() {}
667 
689  virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
690  vec& soft_bits,
691  Soft_Method method = LOGMAP) const;
693  vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
694  Soft_Method method = LOGMAP) const;
695 
696 
719  virtual void demodulate_soft_bits(const cvec& rx_symbols,
720  const cvec& channel, double N0,
721  vec& soft_bits,
722  Soft_Method method = LOGMAP) const;
724  vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel,
725  double N0, Soft_Method method = LOGMAP) const;
726 };
727 
728 
729 // ----------------------------------------------------------------------
730 // BPSK_c : PSK : Modulator<std::complex<double> >
731 // ----------------------------------------------------------------------
732 
758 class BPSK_c : public PSK
759 {
760 public:
762  BPSK_c(): PSK(2) {}
764  virtual ~BPSK_c() {}
765 
767  void modulate_bits(const bvec& bits, cvec& output) const;
769  cvec modulate_bits(const bvec& bits) const;
771  void demodulate_bits(const cvec& signal, bvec& output) const;
773  bvec demodulate_bits(const cvec& signal) const;
774 
794  virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
795  vec& soft_bits,
796  Soft_Method method = LOGMAP) const;
798  vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
799  Soft_Method method = LOGMAP) const;
800 
821  virtual void demodulate_soft_bits(const cvec& rx_symbols,
822  const cvec& channel, double N0,
823  vec& soft_bits,
824  Soft_Method method = LOGMAP) const;
826  vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel,
827  double N0, Soft_Method method = LOGMAP) const;
828 };
829 
830 
831 
832 // ----------------------------------------------------------------------
833 // BPSK : Modulator<double>
834 // ----------------------------------------------------------------------
835 
859 class BPSK : public Modulator<double>
860 {
861 public:
863  BPSK(): Modulator<double>("1.0 -1.0", "0 1") {}
865  virtual ~BPSK() {}
866 
868  void modulate_bits(const bvec& bits, vec& output) const;
870  vec modulate_bits(const bvec& bits) const;
872  void demodulate_bits(const vec& signal, bvec& output) const;
874  bvec demodulate_bits(const vec& signal) const;
875 
893  virtual void demodulate_soft_bits(const vec& rx_symbols, double N0,
894  vec& soft_bits,
895  Soft_Method method = LOGMAP) const;
897  vec demodulate_soft_bits(const vec& rx_symbols, double N0,
898  Soft_Method method = LOGMAP) const;
899 
919  virtual void demodulate_soft_bits(const vec& rx_symbols,
920  const vec& channel, double N0,
921  vec& soft_bits,
922  Soft_Method method = LOGMAP) const;
924  vec demodulate_soft_bits(const vec& rx_symbols, const vec& channel,
925  double N0, Soft_Method method = LOGMAP) const;
926 };
927 
928 
929 // ----------------------------------------------------------------------
930 // PAM_c : Modulator<std::complex<double> >
931 // ----------------------------------------------------------------------
932 
951 class PAM_c : public Modulator<std::complex<double> >
952 {
953 public:
955  PAM_c() {}
957  PAM_c(int M) { set_M(M); }
959  virtual ~PAM_c() {}
961  void set_M(int M);
962 
964  void demodulate_bits(const cvec& signal, bvec& output) const;
966  bvec demodulate_bits(const cvec& signal) const;
967 
1007  virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
1008  vec& soft_bits,
1009  Soft_Method method = LOGMAP) const;
1011  virtual vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
1012  Soft_Method method = LOGMAP) const;
1013 
1052  virtual void demodulate_soft_bits(const cvec& rx_symbols,
1053  const cvec& channel, double N0,
1054  vec& soft_bits,
1055  Soft_Method method = LOGMAP) const;
1057  virtual vec demodulate_soft_bits(const cvec& rx_symbols,
1058  const cvec& channel, double N0,
1059  Soft_Method method = LOGMAP) const;
1060 
1061 protected:
1064 };
1065 
1066 
1067 // ----------------------------------------------------------------------
1068 // PAM : Modulator<double>
1069 // ----------------------------------------------------------------------
1070 
1087 class PAM : public Modulator<double>
1088 {
1089 public:
1091  PAM() {}
1093  PAM(int M) { set_M(M); }
1095  virtual ~PAM() {}
1097  void set_M(int M);
1098 
1100  void demodulate_bits(const vec& signal, bvec& output) const;
1102  bvec demodulate_bits(const vec& signal) const;
1103 
1104 protected:
1107 };
1108 
1109 } // namespace itpp
1110 
1111 #endif // #ifndef MODULATOR_H
SourceForge Logo

Generated on Fri Mar 21 2014 17:14:13 for IT++ by Doxygen 1.8.1.2