IT++ Logo

modulator.h

Go to the documentation of this file.
00001 
00030 #ifndef MODULATOR_H
00031 #define MODULATOR_H
00032 
00033 #include <itpp/base/mat.h>
00034 #include <itpp/base/math/elem_math.h>
00035 #include <itpp/base/math/log_exp.h>
00036 #include <itpp/base/converters.h>
00037 #include <itpp/base/math/min_max.h>
00038 
00039 
00040 namespace itpp {
00041 
00046   enum Soft_Method {
00047     LOGMAP,                     
00048     APPROX                      
00049   };
00050 
00073   template <typename T>
00074   class Modulator {
00075   public:
00077     Modulator();
00079     Modulator(const Vec<T>& symbols, const ivec& bits2symbols);
00081     virtual ~Modulator() {}
00082 
00084     virtual void set(const Vec<T>& symbols, const ivec& bits2symbols);
00085 
00087     virtual int bits_per_symbol() const { return k; }
00089     virtual Vec<T> get_symbols() const { return symbols; }
00107     virtual ivec get_bits2symbols() const { return bits2symbols; }
00108 
00110     virtual void modulate(const ivec& symbolnumbers, Vec<T>& output) const;
00112     virtual Vec<T> modulate(const ivec& symbolnumbers) const;
00113 
00115     virtual void demodulate(const Vec<T>& signal, ivec& output) const;
00117     virtual ivec demodulate(const Vec<T>& signal) const;
00118 
00120     virtual void modulate_bits(const bvec& bits, Vec<T>& output) const;
00122     virtual Vec<T> modulate_bits(const bvec& bits) const;
00123 
00125     virtual void demodulate_bits(const Vec<T>& signal, bvec& bits) const;
00127     virtual bvec demodulate_bits(const Vec<T>& signal) const;
00128 
00168     virtual void demodulate_soft_bits(const Vec<T>& rx_symbols, double N0,
00169                                       vec& soft_bits,
00170                                       Soft_Method method = LOGMAP) const;
00172     virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols, double N0,
00173                                      Soft_Method method = LOGMAP) const;
00174 
00179     virtual void demodulate_soft_bits_approx(const Vec<T>& rx_symbols,
00180                                              double N0, vec& soft_bits) const;
00185     virtual vec demodulate_soft_bits_approx(const Vec<T>& rx_symbols,
00186                                             double N0) const;
00187 
00226     virtual void demodulate_soft_bits(const Vec<T>& rx_symbols,
00227                                       const Vec<T>& channel,
00228                                       double N0, vec& soft_bits,
00229                                       Soft_Method method = LOGMAP) const;
00231     virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols,
00232                                      const Vec<T>& channel,
00233                                      double N0,
00234                                      Soft_Method method = LOGMAP) const;
00235 
00240     virtual void demodulate_soft_bits_approx(const Vec<T>& rx_symbols,
00241                                              const Vec<T>& channel,
00242                                              double N0, vec& soft_bits) const;
00247     virtual vec demodulate_soft_bits_approx(const Vec<T>& rx_symbols,
00248                                             const Vec<T>& channel,
00249                                             double N0) const;
00250 
00251   protected:
00253     bool setup_done;
00255     int k;
00257     int M;
00259     bmat bitmap;
00261     ivec bits2symbols;
00263     Vec<T> symbols;
00266     imat S0;
00269     imat S1;
00270 
00272     void calculate_softbit_matrices(const ivec& bits2symbols);
00273   };
00274 
00275 
00276   // ----------------------------------------------------------------------
00277   // Type definitions of Modulator_1D and Modulator_2D
00278   // ----------------------------------------------------------------------
00279 
00284   typedef Modulator<double> Modulator_1D;
00285 
00290   typedef Modulator<std::complex<double> > Modulator_2D;
00291 
00292 
00293   // ----------------------------------------------------------------------
00294   // Implementation of templated Modulator members
00295   // ----------------------------------------------------------------------
00296 
00297   template<typename T>
00298   Modulator<T>::Modulator() :
00299     setup_done(false), k(0), M(0), bitmap(""), bits2symbols(""), symbols(""),
00300     S0(""), S1("") {}
00301 
00302   template<typename T>
00303   Modulator<T>::Modulator(const Vec<T> &symbols, const ivec &bits2symbols)
00304   {
00305     set(symbols, bits2symbols);
00306   }
00307 
00308   template<typename T>
00309   void Modulator<T>::set(const Vec<T> &in_symbols, const ivec &in_bits2symbols)
00310   {
00311     it_assert(in_symbols.size() == in_bits2symbols.size(),
00312               "Modulator<T>::set(): Number of symbols and bits2symbols does not match");
00313     it_assert(is_even(in_symbols.size()) && (in_symbols.size() > 0),
00314               "Modulator<T>::set(): Number of symbols needs to be even and non-zero");
00315     it_assert((max(in_bits2symbols) == in_bits2symbols.size() - 1)
00316               && (min(in_bits2symbols) == 0), "Modulator<T>::set(): Improper bits2symbol vector");
00317     symbols = in_symbols;
00318     bits2symbols = in_bits2symbols;
00319     M = bits2symbols.size();
00320     k = levels2bits(M);
00321     bitmap.set_size(M, k);
00322     for (int m = 0; m < M; m++) {
00323       bitmap.set_row(bits2symbols(m), dec2bin(k, m));
00324     }
00325     calculate_softbit_matrices(bits2symbols);
00326     setup_done = true;
00327   }
00328 
00329 
00330   template<typename T>
00331   void Modulator<T>::modulate(const ivec &symbolnumbers, Vec<T>& output) const
00332   {
00333     it_assert_debug(setup_done, "Modulator<T>::modulate(): Modulator not ready.");
00334     output.set_size(symbolnumbers.length());
00335     for (int i = 0; i < symbolnumbers.length(); i++)
00336       output(i) = symbols(symbolnumbers(i));
00337   }
00338 
00339   template<typename T>
00340   Vec<T> Modulator<T>::modulate(const ivec &symbolnumbers) const
00341   {
00342     Vec<T> output(symbolnumbers.length());
00343     modulate(symbolnumbers, output);
00344     return output;
00345   }
00346 
00347 
00348   template<typename T>
00349   void Modulator<T>::demodulate(const Vec<T> &signal, ivec& output) const
00350   {
00351     it_assert_debug(setup_done, "Modulator<T>::demodulate(): Modulator not ready.");
00352     double dist, mindist;
00353     int closest;
00354     output.set_size(signal.size());
00355 
00356     for (int i = 0; i < signal.size(); i++) {
00357       mindist = std::abs(symbols(0) - signal(i));
00358       closest = 0;
00359       for (int j = 1; j < M; j++) {
00360         dist = std::abs(symbols(j) - signal(i));
00361         if (dist < mindist) {
00362           mindist = dist;
00363           closest = j;
00364         }
00365       }
00366       output(i) = closest;
00367     }
00368   }
00369 
00370   template<typename T>
00371   ivec Modulator<T>::demodulate(const Vec<T>& signal) const
00372   {
00373     ivec output(signal.length());
00374     demodulate(signal, output);
00375     return output;
00376   }
00377 
00378 
00379   template<typename T>
00380   void Modulator<T>::modulate_bits(const bvec &bits, Vec<T> &output) const
00381   {
00382     it_assert_debug(setup_done, "Modulator<T>::modulate_bits(): Modulator not ready.");
00383     // Check if some bits have to be cut and print warning message in such
00384     // case.
00385     if (bits.length() % k) {
00386       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.");
00387     }
00388     int no_symbols = bits.length() / k;
00389     output.set_size(no_symbols);
00390     for (int i = 0; i < no_symbols; i++) {
00391       output(i) = symbols(bits2symbols(bin2dec(bits.mid(i*k, k))));
00392     }
00393   }
00394 
00395   template<typename T>
00396   Vec<T> Modulator<T>::modulate_bits(const bvec &bits) const
00397   {
00398     Vec<T> output;
00399     modulate_bits(bits, output);
00400     return output;
00401   }
00402 
00403   template<typename T>
00404   void Modulator<T>::demodulate_bits(const Vec<T> &signal, bvec &bits) const
00405   {
00406     it_assert_debug(setup_done, "Modulator<T>::demodulate_bist(): Modulator not ready.");
00407     double dist, mindist;
00408     int closest;
00409     bits.set_size(k*signal.size());
00410 
00411     for (int i = 0; i < signal.size(); i++) {
00412       mindist = std::abs(symbols(0) - signal(i));
00413       closest = 0;
00414       for (int j = 1; j < M; j++) {
00415         dist = std::abs(symbols(j) - signal(i));
00416         if (dist < mindist) {
00417           mindist = dist;
00418           closest = j;
00419         }
00420       }
00421       bits.replace_mid(i*k, bitmap.get_row(closest));
00422     }
00423   }
00424 
00425   template<typename T>
00426   bvec Modulator<T>::demodulate_bits(const Vec<T> &signal) const
00427   {
00428     bvec bits;
00429     demodulate_bits(signal, bits);
00430     return bits;
00431   }
00432 
00433 
00434   template<typename T>
00435   void Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols, double N0,
00436                                           vec &soft_bits,
00437                                           Soft_Method method) const
00438   {
00439     it_assert_debug(setup_done, "Modulator<T>::demodulate_soft_bits(): Modulator not ready.");
00440     double P0, P1, d0min, d1min, temp;
00441     vec metric(M);
00442 
00443     soft_bits.set_size(k * rx_symbols.size());
00444 
00445     if (method == LOGMAP) {
00446       for (int l = 0; l < rx_symbols.size(); l++) {
00447         for (int j = 0; j < M; j++) {
00448           metric(j) = std::exp(-sqr(rx_symbols(l) - symbols(j)) / N0);
00449         }
00450         for (int i = 0; i < k; i++) {
00451           P0 = P1 = 0;
00452           for (int j = 0; j < (M >> 1); j++) {
00453             P0 += metric(S0(i, j));
00454             P1 += metric(S1(i, j));
00455           }
00456           soft_bits(l*k+i) = trunc_log(P0) - trunc_log(P1);
00457         }
00458       }
00459     }
00460     else { // method == APPROX
00461       for (int l = 0; l < rx_symbols.size(); l++) {
00462         for (int j = 0; j < M; j++) {
00463           metric(j) = sqr(rx_symbols(l) - symbols(j));
00464         }
00465         for (int i = 0; i < k; i++) {
00466           d0min = d1min = std::numeric_limits<double>::max();
00467           for (int j = 0; j < (M >> 1); j++) {
00468             temp = metric(S0(i, j));
00469             if (temp < d0min) { d0min = temp; }
00470             temp = metric(S1(i, j));
00471             if (temp < d1min) { d1min = temp; }
00472           }
00473           soft_bits(l*k+i) = (-d0min + d1min) / N0;
00474         }
00475       }
00476     }
00477   }
00478 
00479   template<typename T>
00480   vec Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols,
00481                                          double N0,
00482                                          Soft_Method method) const
00483   {
00484     vec output;
00485     demodulate_soft_bits(rx_symbols, N0, output, method);
00486     return output;
00487   }
00488 
00489   template<typename T>
00490   void Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols,
00491                                                  double N0,
00492                                                  vec &soft_bits) const
00493   {
00494     it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead.");
00495     demodulate_soft_bits(rx_symbols, N0, soft_bits, APPROX);
00496   }
00497 
00498   template<typename T>
00499   vec Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols,
00500                                                 double N0) const
00501   {
00502     it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead.");
00503     vec output;
00504     demodulate_soft_bits(rx_symbols, N0, output, APPROX);
00505     return output;
00506   }
00507 
00508 
00509   template<typename T>
00510   void Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols,
00511                                           const Vec<T> &channel, double N0,
00512                                           vec &soft_bits,
00513                                           Soft_Method method) const
00514   {
00515     it_assert_debug(setup_done, "Modulator_2D::demodulate_soft_bits(): Modulator not ready.");
00516     double P0, P1, d0min, d1min, temp;
00517     vec metric(M);
00518 
00519     soft_bits.set_size(k * rx_symbols.size());
00520 
00521     if (method == LOGMAP) {
00522       for (int l = 0; l < rx_symbols.size(); l++) {
00523         for (int j = 0; j < M; j++) {
00524           metric(j) = std::exp(-sqr(rx_symbols(l) - channel(l) * symbols(j))
00525                                / N0);
00526         }
00527         for (int i = 0; i < k; i++) {
00528           P0 = P1 = 0;
00529           for (int j = 0; j < (M >> 1); j++) {
00530             P0 += metric(S0(i, j));
00531             P1 += metric(S1(i, j));
00532           }
00533           soft_bits(l*k+i) = trunc_log(P0) - trunc_log(P1);
00534         }
00535       }
00536     }
00537     else { // method == APPROX
00538       for (int l = 0; l < rx_symbols.size(); l++) {
00539         for (int j = 0; j < M; j++) {
00540           metric(j) = sqr(rx_symbols(l) - channel(l) * symbols(j));
00541         }
00542         for (int i = 0; i < k; i++) {
00543           d0min = d1min = std::numeric_limits<double>::max();
00544           for (int j = 0; j < (M >> 1); j++) {
00545             temp = metric(S0(i, j));
00546             if (temp < d0min) { d0min = temp; }
00547             temp = metric(S1(i, j));
00548             if (temp < d1min) { d1min = temp; }
00549           }
00550           soft_bits(l*k+i) = (-d0min + d1min) / N0;
00551         }
00552       }
00553     }
00554   }
00555 
00556   template<typename T>
00557   vec Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols,
00558                                          const Vec<T> &channel,
00559                                          double N0,
00560                                          Soft_Method method) const
00561   {
00562     vec output;
00563     demodulate_soft_bits(rx_symbols, channel, N0, output, method);
00564     return output;
00565   }
00566 
00567   template<typename T>
00568   void Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols,
00569                                                  const Vec<T> &channel,
00570                                                  double N0,
00571                                                  vec &soft_bits) const
00572   {
00573     it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead.");
00574     demodulate_soft_bits(rx_symbols, channel, N0, soft_bits, APPROX);
00575   }
00576 
00577   template<typename T>
00578   vec Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols,
00579                                                 const Vec<T> &channel,
00580                                                 double N0) const
00581   {
00582     it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead.");
00583     vec output;
00584     demodulate_soft_bits(rx_symbols, channel, N0, output, APPROX);
00585     return output;
00586   }
00587 
00588 
00589   template<typename T>
00590   void Modulator<T>::calculate_softbit_matrices(const ivec& in_bits2symbols)
00591   {
00592     int count0, count1;
00593 
00594     // Allocate storage space for the result matrices:
00595     S0.set_size(k, M >> 1, false);
00596     S1.set_size(k, M >> 1, false);
00597 
00598     for (int i = 0; i < k; i++) {
00599       count0 = 0;
00600       count1 = 0;
00601       for (int j = 0; j < M; j++) {
00602         if (bitmap(j, i) == bin(0)) {
00603           S0(i, count0++) = j;
00604         }
00605         else {
00606           S1(i, count1++) = j;
00607         }
00608       }
00609     }
00610   }
00611 
00612 
00613 
00614   // ----------------------------------------------------------------------
00615   // QAM : Modulator_2D
00616   // ----------------------------------------------------------------------
00617 
00638   class QAM : public Modulator<std::complex<double> > {
00639   public:
00641     QAM() {}
00643     QAM(int M) { set_M(M); }
00645     virtual ~QAM() { }
00647     void set_M(int M);
00648 
00650     void demodulate_bits(const cvec& signal, bvec& bits) const;
00652     bvec demodulate_bits(const cvec& signal) const;
00653 
00654   protected:
00656     int L;
00658     double scaling_factor;
00659   };
00660 
00661 
00662   // ----------------------------------------------------------------------
00663   // PSK : Modulator<std::complex<double> >
00664   // ----------------------------------------------------------------------
00665 
00686   class PSK : public Modulator<std::complex<double> > {
00687   public:
00689     PSK() {}
00691     PSK(int M) { set_M(M); }
00693     virtual ~PSK() { }
00695     void set_M(int M);
00696 
00698     void demodulate_bits(const cvec& signal, bvec& bits) const;
00700     bvec demodulate_bits(const cvec& signal) const;
00701   };
00702 
00703 
00704   // ----------------------------------------------------------------------
00705   // QPSK : PSK : Modulator<std::complex<double> >
00706   // ----------------------------------------------------------------------
00707 
00727   class QPSK : public PSK {
00728   public:
00730     QPSK(): PSK(4) {}
00732     virtual ~QPSK() {}
00733 
00755     virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
00756                                       vec& soft_bits,
00757                                       Soft_Method method = LOGMAP) const;
00759     vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
00760                              Soft_Method method = LOGMAP) const;
00761 
00762 
00785     virtual void demodulate_soft_bits(const cvec& rx_symbols,
00786                                       const cvec& channel, double N0,
00787                                       vec& soft_bits,
00788                                       Soft_Method method = LOGMAP) const;
00790     vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel,
00791                              double N0, Soft_Method method = LOGMAP) const;
00792   };
00793 
00794 
00795   // ----------------------------------------------------------------------
00796   // BPSK_c : PSK : Modulator<std::complex<double> >
00797   // ----------------------------------------------------------------------
00798 
00824   class BPSK_c : public PSK {
00825   public:
00827     BPSK_c(): PSK(2) {}
00829     virtual ~BPSK_c() {}
00830 
00832     void modulate_bits(const bvec& bits, cvec& output) const;
00834     cvec modulate_bits(const bvec& bits) const;
00836     void demodulate_bits(const cvec& signal, bvec& output) const;
00838     bvec demodulate_bits(const cvec& signal) const;
00839 
00859     virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
00860                                       vec& soft_bits,
00861                                       Soft_Method method = LOGMAP) const;
00863     vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
00864                              Soft_Method method = LOGMAP) const;
00865 
00886     virtual void demodulate_soft_bits(const cvec& rx_symbols,
00887                                       const cvec& channel, double N0,
00888                                       vec& soft_bits,
00889                                       Soft_Method method = LOGMAP) const;
00891     vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel,
00892                              double N0, Soft_Method method = LOGMAP) const;
00893   };
00894 
00895 
00896 
00897   // ----------------------------------------------------------------------
00898   // BPSK : Modulator<double>
00899   // ----------------------------------------------------------------------
00900 
00924   class BPSK : public Modulator<double> {
00925   public:
00927     BPSK(): Modulator<double>("1.0 -1.0", "0 1") {}
00929     virtual ~BPSK() {}
00930 
00932     void modulate_bits(const bvec& bits, vec& output) const;
00934     vec modulate_bits(const bvec& bits) const;
00936     void demodulate_bits(const vec& signal, bvec& output) const;
00938     bvec demodulate_bits(const vec& signal) const;
00939 
00957     virtual void demodulate_soft_bits(const vec& rx_symbols, double N0,
00958                                       vec& soft_bits,
00959                                       Soft_Method method = LOGMAP) const;
00961     vec demodulate_soft_bits(const vec& rx_symbols, double N0,
00962                              Soft_Method method = LOGMAP) const;
00963 
00983     virtual void demodulate_soft_bits(const vec& rx_symbols,
00984                                       const vec& channel, double N0,
00985                                       vec& soft_bits,
00986                                       Soft_Method method = LOGMAP) const;
00988     vec demodulate_soft_bits(const vec& rx_symbols, const vec& channel,
00989                              double N0, Soft_Method method = LOGMAP) const;
00990   };
00991 
00992 
00993   // ----------------------------------------------------------------------
00994   // PAM_c : Modulator<std::complex<double> >
00995   // ----------------------------------------------------------------------
00996 
01015   class PAM_c : public Modulator<std::complex<double> > {
01016   public:
01018     PAM_c() {}
01020     PAM_c(int M) { set_M(M); }
01022     virtual ~PAM_c() {}
01024     void set_M(int M);
01025 
01027     void demodulate_bits(const cvec& signal, bvec& output) const;
01029     bvec demodulate_bits(const cvec& signal) const;
01030 
01070     virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
01071                                       vec& soft_bits,
01072                                       Soft_Method method = LOGMAP) const;
01074     virtual vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
01075                                      Soft_Method method = LOGMAP) const;
01076 
01115     virtual void demodulate_soft_bits(const cvec& rx_symbols,
01116                                       const cvec& channel, double N0,
01117                                       vec& soft_bits,
01118                                       Soft_Method method = LOGMAP) const;
01120     virtual vec demodulate_soft_bits(const cvec& rx_symbols,
01121                                      const cvec& channel, double N0,
01122                                      Soft_Method method = LOGMAP) const;
01123 
01124   protected:
01126     double scaling_factor;
01127   };
01128 
01129 
01130   // ----------------------------------------------------------------------
01131   // PAM : Modulator<double>
01132   // ----------------------------------------------------------------------
01133 
01150   class PAM : public Modulator<double> {
01151   public:
01153     PAM() {}
01155     PAM(int M) { set_M(M); }
01157     virtual ~PAM() {}
01159     void set_M(int M);
01160 
01162     void demodulate_bits(const vec& signal, bvec& output) const;
01164     bvec demodulate_bits(const vec& signal) const;
01165 
01166   protected:
01168     double scaling_factor;
01169   };
01170 
01171 } // namespace itpp
01172 
01173 #endif // #ifndef MODULATOR_H
SourceForge Logo

Generated on Sat Apr 19 10:57:51 2008 for IT++ by Doxygen 1.5.5