IT++ Logo
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 #include <itpp/itexports.h>
38 
39 
40 namespace itpp
41 {
42 
50 };
51 
74 template <typename T>
75 class Modulator
76 {
77 public:
79  Modulator();
81  Modulator(const Vec<T>& symbols, const ivec& bits2symbols);
83  virtual ~Modulator() {}
84 
86  virtual void set(const Vec<T>& symbols, const ivec& bits2symbols);
87 
89  virtual int bits_per_symbol() const { return k; }
90 
92  virtual int get_k() const { return k; }
93 
95  virtual int get_M() const { return M; }
96 
98  virtual Vec<T> get_symbols() const { return symbols; }
99 
117  virtual ivec get_bits2symbols() const { return bits2symbols; }
118 
120  virtual void modulate(const ivec& symbolnumbers, Vec<T>& output) const;
122  virtual Vec<T> modulate(const ivec& symbolnumbers) const;
123 
125  virtual void demodulate(const Vec<T>& signal, ivec& output) const;
127  virtual ivec demodulate(const Vec<T>& signal) const;
128 
130  virtual void modulate_bits(const bvec& bits, Vec<T>& output) const;
132  virtual Vec<T> modulate_bits(const bvec& bits) const;
133 
135  virtual void demodulate_bits(const Vec<T>& signal, bvec& bits) const;
137  virtual bvec demodulate_bits(const Vec<T>& signal) const;
138 
178  virtual void demodulate_soft_bits(const Vec<T>& rx_symbols, double N0,
179  vec& soft_bits,
180  Soft_Method method = LOGMAP) const;
182  virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols, double N0,
183  Soft_Method method = LOGMAP) const;
184 
223  virtual void demodulate_soft_bits(const Vec<T>& rx_symbols,
224  const Vec<T>& channel,
225  double N0, vec& soft_bits,
226  Soft_Method method = LOGMAP) const;
228  virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols,
229  const Vec<T>& channel,
230  double N0,
231  Soft_Method method = LOGMAP) const;
232 
233 protected:
237  int k;
239  int M;
248  imat S0;
251  imat S1;
252 
255 };
256 
257 
258 // ----------------------------------------------------------------------
259 // Type definitions of Modulator_1D and Modulator_2D
260 // ----------------------------------------------------------------------
261 
267 
273 
274 
275 // ----------------------------------------------------------------------
276 // Implementation of templated Modulator members
277 // ----------------------------------------------------------------------
278 
279 template<typename T>
281  setup_done(false), k(0), M(0), bitmap(""), bits2symbols(""), symbols(""),
282  S0(""), S1("") {}
283 
284 template<typename T>
285 Modulator<T>::Modulator(const Vec<T> &symbols, const ivec &bits2symbols)
286 {
287  set(symbols, bits2symbols);
288 }
289 
290 template<typename T>
291 void Modulator<T>::set(const Vec<T> &in_symbols, const ivec &in_bits2symbols)
292 {
293  it_assert(in_symbols.size() == in_bits2symbols.size(),
294  "Modulator<T>::set(): Number of symbols and bits2symbols does not match");
295  it_assert(is_even(in_symbols.size()) && (in_symbols.size() > 0),
296  "Modulator<T>::set(): Number of symbols needs to be even and non-zero");
297  it_assert((max(in_bits2symbols) == in_bits2symbols.size() - 1)
298  && (min(in_bits2symbols) == 0), "Modulator<T>::set(): Improper bits2symbol vector");
299  symbols = in_symbols;
300  bits2symbols = in_bits2symbols;
301  M = bits2symbols.size();
302  k = levels2bits(M);
303  bitmap.set_size(M, k);
304  for (int m = 0; m < M; m++) {
305  bitmap.set_row(bits2symbols(m), dec2bin(k, m));
306  }
307  calculate_softbit_matrices();
308  setup_done = true;
309 }
310 
311 
312 template<typename T>
313 void Modulator<T>::modulate(const ivec &symbolnumbers, Vec<T>& output) const
314 {
315  it_assert_debug(setup_done, "Modulator<T>::modulate(): Modulator not ready.");
316  output.set_size(symbolnumbers.length());
317  for (int i = 0; i < symbolnumbers.length(); i++)
318  output(i) = symbols(symbolnumbers(i));
319 }
320 
321 template<typename T>
322 Vec<T> Modulator<T>::modulate(const ivec &symbolnumbers) const
323 {
324  Vec<T> output(symbolnumbers.length());
325  modulate(symbolnumbers, output);
326  return output;
327 }
328 
329 
330 template<typename T>
331 void Modulator<T>::demodulate(const Vec<T> &signal, ivec& output) const
332 {
333  it_assert_debug(setup_done, "Modulator<T>::demodulate(): Modulator not ready.");
334  double dist, mindist;
335  int closest;
336  output.set_size(signal.size());
337 
338  for (int i = 0; i < signal.size(); i++) {
339  mindist = std::abs(symbols(0) - signal(i));
340  closest = 0;
341  for (int j = 1; j < M; j++) {
342  dist = std::abs(symbols(j) - signal(i));
343  if (dist < mindist) {
344  mindist = dist;
345  closest = j;
346  }
347  }
348  output(i) = closest;
349  }
350 }
351 
352 template<typename T>
353 ivec Modulator<T>::demodulate(const Vec<T>& signal) const
354 {
355  ivec output(signal.length());
356  demodulate(signal, output);
357  return output;
358 }
359 
360 
361 template<typename T>
362 void Modulator<T>::modulate_bits(const bvec &bits, Vec<T> &output) const
363 {
364  it_assert_debug(setup_done, "Modulator<T>::modulate_bits(): Modulator not ready.");
365  // Check if some bits have to be cut and print warning message in such
366  // case.
367  if (bits.length() % k) {
368  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.");
369  }
370  int no_symbols = bits.length() / k;
371  output.set_size(no_symbols);
372  for (int i = 0; i < no_symbols; i++) {
373  output(i) = symbols(bits2symbols(bin2dec(bits.mid(i * k, k))));
374  }
375 }
376 
377 template<typename T>
378 Vec<T> Modulator<T>::modulate_bits(const bvec &bits) const
379 {
380  Vec<T> output;
381  modulate_bits(bits, output);
382  return output;
383 }
384 
385 template<typename T>
386 void Modulator<T>::demodulate_bits(const Vec<T> &signal, bvec &bits) const
387 {
388  it_assert_debug(setup_done, "Modulator<T>::demodulate_bist(): Modulator not ready.");
389  double dist, mindist;
390  int closest;
391  bits.set_size(k*signal.size());
392 
393  for (int i = 0; i < signal.size(); i++) {
394  mindist = std::abs(symbols(0) - signal(i));
395  closest = 0;
396  for (int j = 1; j < M; j++) {
397  dist = std::abs(symbols(j) - signal(i));
398  if (dist < mindist) {
399  mindist = dist;
400  closest = j;
401  }
402  }
403  bits.replace_mid(i*k, bitmap.get_row(closest));
404  }
405 }
406 
407 template<typename T>
408 bvec Modulator<T>::demodulate_bits(const Vec<T> &signal) const
409 {
410  bvec bits;
411  demodulate_bits(signal, bits);
412  return bits;
413 }
414 
415 
416 template<typename T>
417 void Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols, double N0,
418  vec &soft_bits,
419  Soft_Method method) const
420 {
421  it_assert_debug(setup_done, "Modulator<T>::demodulate_soft_bits(): Modulator not ready.");
422  double P0, P1, d0min, d1min, temp;
423  vec metric(M);
424 
425  soft_bits.set_size(k * rx_symbols.size());
426 
427  if (method == LOGMAP) {
428  for (int l = 0; l < rx_symbols.size(); l++) {
429  for (int j = 0; j < M; j++) {
430  metric(j) = std::exp(-sqr(rx_symbols(l) - symbols(j)) / N0);
431  }
432  for (int i = 0; i < k; i++) {
433  P0 = P1 = 0;
434  for (int j = 0; j < (M >> 1); j++) {
435  P0 += metric(S0(i, j));
436  P1 += metric(S1(i, j));
437  }
438  soft_bits(l*k + i) = trunc_log(P0) - trunc_log(P1);
439  }
440  }
441  }
442  else { // method == APPROX
443  for (int l = 0; l < rx_symbols.size(); l++) {
444  for (int j = 0; j < M; j++) {
445  metric(j) = sqr(rx_symbols(l) - symbols(j));
446  }
447  for (int i = 0; i < k; i++) {
448  d0min = d1min = std::numeric_limits<double>::max();
449  for (int j = 0; j < (M >> 1); j++) {
450  temp = metric(S0(i, j));
451  if (temp < d0min) { d0min = temp; }
452  temp = metric(S1(i, j));
453  if (temp < d1min) { d1min = temp; }
454  }
455  soft_bits(l*k + i) = (-d0min + d1min) / N0;
456  }
457  }
458  }
459 }
460 
461 template<typename T>
463  double N0,
464  Soft_Method method) const
465 {
466  vec output;
467  demodulate_soft_bits(rx_symbols, N0, output, method);
468  return output;
469 }
470 
471 template<typename T>
473  const Vec<T> &channel, double N0,
474  vec &soft_bits,
475  Soft_Method method) const
476 {
477  it_assert_debug(setup_done, "Modulator_2D::demodulate_soft_bits(): Modulator not ready.");
478  double P0, P1, d0min, d1min, temp;
479  vec metric(M);
480 
481  soft_bits.set_size(k * rx_symbols.size());
482 
483  if (method == LOGMAP) {
484  for (int l = 0; l < rx_symbols.size(); l++) {
485  for (int j = 0; j < M; j++) {
486  metric(j) = std::exp(-sqr(rx_symbols(l) - channel(l) * symbols(j))
487  / N0);
488  }
489  for (int i = 0; i < k; i++) {
490  P0 = P1 = 0;
491  for (int j = 0; j < (M >> 1); j++) {
492  P0 += metric(S0(i, j));
493  P1 += metric(S1(i, j));
494  }
495  soft_bits(l*k + i) = trunc_log(P0) - trunc_log(P1);
496  }
497  }
498  }
499  else { // method == APPROX
500  for (int l = 0; l < rx_symbols.size(); l++) {
501  for (int j = 0; j < M; j++) {
502  metric(j) = sqr(rx_symbols(l) - channel(l) * symbols(j));
503  }
504  for (int i = 0; i < k; i++) {
505  d0min = d1min = std::numeric_limits<double>::max();
506  for (int j = 0; j < (M >> 1); j++) {
507  temp = metric(S0(i, j));
508  if (temp < d0min) { d0min = temp; }
509  temp = metric(S1(i, j));
510  if (temp < d1min) { d1min = temp; }
511  }
512  soft_bits(l*k + i) = (-d0min + d1min) / N0;
513  }
514  }
515  }
516 }
517 
518 template<typename T>
520  const Vec<T> &channel,
521  double N0,
522  Soft_Method method) const
523 {
524  vec output;
525  demodulate_soft_bits(rx_symbols, channel, N0, output, method);
526  return output;
527 }
528 
529 template<typename T>
531 {
532  int count0, count1;
533 
534  // Allocate storage space for the result matrices:
535  S0.set_size(k, M >> 1, false);
536  S1.set_size(k, M >> 1, false);
537 
538  for (int i = 0; i < k; i++) {
539  count0 = 0;
540  count1 = 0;
541  for (int j = 0; j < M; j++) {
542  if (bitmap(j, i) == bin(0)) {
543  S0(i, count0++) = j;
544  }
545  else {
546  S1(i, count1++) = j;
547  }
548  }
549  }
550 }
551 
553 
554 // ----------------------------------------------------------------------
555 // Instantiations
556 // ----------------------------------------------------------------------
557 ITPP_EXPORT_TEMPLATE template class ITPP_EXPORT Modulator<double>;
558 ITPP_EXPORT_TEMPLATE template class ITPP_EXPORT Modulator<std::complex<double> >;
559 
561 
562 // ----------------------------------------------------------------------
563 // QAM : Modulator_2D
564 // ----------------------------------------------------------------------
565 
586 class ITPP_EXPORT QAM : public Modulator<std::complex<double> >
587 {
588 public:
590  QAM() {}
592  QAM(int M) { set_M(M); }
594  virtual ~QAM() { }
596  void set_M(int M);
597 
599  void demodulate_bits(const cvec& signal, bvec& bits) const;
601  bvec demodulate_bits(const cvec& signal) const;
602 
603 protected:
605  int L;
608 };
609 
610 
611 // ----------------------------------------------------------------------
612 // PSK : Modulator<std::complex<double> >
613 // ----------------------------------------------------------------------
614 
635 class ITPP_EXPORT PSK : public Modulator<std::complex<double> >
636 {
637 public:
639  PSK() {}
641  PSK(int M) { set_M(M); }
643  virtual ~PSK() { }
645  void set_M(int M);
646 
648  void demodulate_bits(const cvec& signal, bvec& bits) const;
650  bvec demodulate_bits(const cvec& signal) const;
651 };
652 
653 
654 // ----------------------------------------------------------------------
655 // QPSK : PSK : Modulator<std::complex<double> >
656 // ----------------------------------------------------------------------
657 
677 class ITPP_EXPORT QPSK : public PSK
678 {
679 public:
681  QPSK(): PSK(4) {}
683  virtual ~QPSK() {}
684 
706  virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
707  vec& soft_bits,
708  Soft_Method method = LOGMAP) const;
710  vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
711  Soft_Method method = LOGMAP) const;
712 
713 
736  virtual void demodulate_soft_bits(const cvec& rx_symbols,
737  const cvec& channel, double N0,
738  vec& soft_bits,
739  Soft_Method method = LOGMAP) const;
741  vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel,
742  double N0, Soft_Method method = LOGMAP) const;
743 };
744 
745 
746 // ----------------------------------------------------------------------
747 // BPSK_c : PSK : Modulator<std::complex<double> >
748 // ----------------------------------------------------------------------
749 
775 class ITPP_EXPORT BPSK_c : public PSK
776 {
777 public:
779  BPSK_c(): PSK(2) {}
781  virtual ~BPSK_c() {}
782 
784  void modulate_bits(const bvec& bits, cvec& output) const;
786  cvec modulate_bits(const bvec& bits) const;
788  void demodulate_bits(const cvec& signal, bvec& output) const;
790  bvec demodulate_bits(const cvec& signal) const;
791 
811  virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
812  vec& soft_bits,
813  Soft_Method method = LOGMAP) const;
815  vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
816  Soft_Method method = LOGMAP) const;
817 
838  virtual void demodulate_soft_bits(const cvec& rx_symbols,
839  const cvec& channel, double N0,
840  vec& soft_bits,
841  Soft_Method method = LOGMAP) const;
843  vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel,
844  double N0, Soft_Method method = LOGMAP) const;
845 };
846 
847 
848 
849 // ----------------------------------------------------------------------
850 // BPSK : Modulator<double>
851 // ----------------------------------------------------------------------
852 
876 class ITPP_EXPORT BPSK : public Modulator<double>
877 {
878 public:
880  BPSK(): Modulator<double>("1.0 -1.0", "0 1") {}
882  virtual ~BPSK() {}
883 
885  void modulate_bits(const bvec& bits, vec& output) const;
887  vec modulate_bits(const bvec& bits) const;
889  void demodulate_bits(const vec& signal, bvec& output) const;
891  bvec demodulate_bits(const vec& signal) const;
892 
910  virtual void demodulate_soft_bits(const vec& rx_symbols, double N0,
911  vec& soft_bits,
912  Soft_Method method = LOGMAP) const;
914  vec demodulate_soft_bits(const vec& rx_symbols, double N0,
915  Soft_Method method = LOGMAP) const;
916 
936  virtual void demodulate_soft_bits(const vec& rx_symbols,
937  const vec& channel, double N0,
938  vec& soft_bits,
939  Soft_Method method = LOGMAP) const;
941  vec demodulate_soft_bits(const vec& rx_symbols, const vec& channel,
942  double N0, Soft_Method method = LOGMAP) const;
943 };
944 
945 
946 // ----------------------------------------------------------------------
947 // PAM_c : Modulator<std::complex<double> >
948 // ----------------------------------------------------------------------
949 
968 class ITPP_EXPORT PAM_c : public Modulator<std::complex<double> >
969 {
970 public:
972  PAM_c() {}
974  PAM_c(int M) { set_M(M); }
976  virtual ~PAM_c() {}
978  void set_M(int M);
979 
981  void demodulate_bits(const cvec& signal, bvec& output) const;
983  bvec demodulate_bits(const cvec& signal) const;
984 
1024  virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
1025  vec& soft_bits,
1026  Soft_Method method = LOGMAP) const;
1028  virtual vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
1029  Soft_Method method = LOGMAP) const;
1030 
1069  virtual void demodulate_soft_bits(const cvec& rx_symbols,
1070  const cvec& channel, double N0,
1071  vec& soft_bits,
1072  Soft_Method method = LOGMAP) const;
1074  virtual vec demodulate_soft_bits(const cvec& rx_symbols,
1075  const cvec& channel, double N0,
1076  Soft_Method method = LOGMAP) const;
1077 
1078 protected:
1081 };
1082 
1083 
1084 // ----------------------------------------------------------------------
1085 // PAM : Modulator<double>
1086 // ----------------------------------------------------------------------
1087 
1104 class ITPP_EXPORT PAM : public Modulator<double>
1105 {
1106 public:
1108  PAM() {}
1110  PAM(int M) { set_M(M); }
1112  virtual ~PAM() {}
1114  void set_M(int M);
1115 
1117  void demodulate_bits(const vec& signal, bvec& output) const;
1119  bvec demodulate_bits(const vec& signal) const;
1120 
1121 protected:
1124 };
1125 
1126 } // namespace itpp
1127 
1128 #endif // #ifndef MODULATOR_H
SourceForge Logo

Generated on Sat Jul 6 2013 10:54:22 for IT++ by Doxygen 1.8.2