User Manual, Developers Guide and API Documentation

MI2PER.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * This file is part of openWNS (open Wireless Network Simulator)
00003  * _____________________________________________________________________________
00004  *
00005  * Copyright (C) 2004-2007
00006  * Chair of Communication Networks (ComNets)
00007  * Kopernikusstr. 5, D-52074 Aachen, Germany
00008  * phone: ++49-241-80-27910,
00009  * fax: ++49-241-80-22242
00010  * email: info@openwns.org
00011  * www: http://www.openwns.org
00012  * _____________________________________________________________________________
00013  *
00014  * openWNS is free software; you can redistribute it and/or modify it under the
00015  * terms of the GNU Lesser General Public License version 2 as published by the
00016  * Free Software Foundation;
00017  *
00018  * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
00019  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00020  * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00021  * details.
00022  *
00023  * You should have received a copy of the GNU Lesser General Public License
00024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025  *
00026  ******************************************************************************/
00027 
00028 #include <RISE/plmapping/MI2PER.hpp>
00029 #include <RISE/plmapping/CodeRates.hpp>
00030 
00031 #include <cmath>
00032 #include <sstream>
00033 #include <vector>
00034 #include <WNS/StaticFactoryBroker.hpp>
00035 #include <WNS/PyConfigViewCreator.hpp>
00036 #include <WNS/Assure.hpp>
00037 #include <WNS/Ttos.hpp>
00038 
00039 using namespace rise;
00040 using namespace rise::plmapping;
00041 
00042 STATIC_FACTORY_BROKER_REGISTER(CoderFullMapping,
00043                                wns::service::phy::phymode::CoderFullMappingInterface,
00044                                "rise.plmapping.CoderFullMapping");
00045 
00046 STATIC_FACTORY_REGISTER_WITH_CREATOR( TableCoder, CoderFullSpecification, "rise.CoderSpecification.Table", wns::PyConfigViewCreator);
00047 STATIC_FACTORY_REGISTER_WITH_CREATOR( FormulaCoder, CoderFullSpecification, "rise.CoderSpecification.Formula", wns::PyConfigViewCreator);
00048 
00049 STATIC_FACTORY_REGISTER_WITH_CREATOR( GENERICM2P, wns::service::phy::phymode::MI2PERMappingInterface, "rise.plmapping.GENERIC", wns::PyConfigViewCreator);
00050 STATIC_FACTORY_REGISTER_WITH_CREATOR( WINNERM2P,  wns::service::phy::phymode::MI2PERMappingInterface, "rise.plmapping.WINNER",  wns::PyConfigViewCreator);
00051 STATIC_FACTORY_REGISTER_WITH_CREATOR( FixedM2P,   wns::service::phy::phymode::MI2PERMappingInterface, "rise.plmapping.Fixed",   wns::PyConfigViewCreator);
00052 STATIC_FACTORY_REGISTER_WITH_CREATOR( FormulaM2P, wns::service::phy::phymode::MI2PERMappingInterface, "rise.plmapping.Formula", wns::PyConfigViewCreator);
00053 
00054 
00055 TableCoder::TableCoder(const wns::pyconfig::View& config)
00056     : CoderFullSpecification(config),
00057       numberOfCWLs(0),
00058       logger(std::string("RISE"), std::string("MI2PERmapper"))
00059       //logger(config.get("logger")) // TODO
00060 {
00061     MESSAGE_SINGLE(VERBOSE, logger, "TableCoder::Constructor:");
00062     // ugly, but we have to set some base class members here
00063     assure(config.knows("coderName"),"PyConfig: missing: coderName");
00064     name   = config.get<std::string>("coderName"); // inherited member name
00065     coding = config.get<Coding>("index"); // inherited
00066     rate   = config.get<double>("rate"); // inherited
00067     codeWordLengths.clear(); // empty vector
00068     vectorOfTablesByCWLSize.clear(); // empty vector
00069 
00070     assure(config.knows("cwlTable"),"PyConfig: missing: cwlTable");
00071     numberOfCWLs = config.len("cwlTable"); // member
00072     if (numberOfCWLs==0) {
00073         MESSAGE_SINGLE(NORMAL, logger, "Coder["<<coding<<"]="<<name<<": empty table.");
00074     } else {
00075         MESSAGE_BEGIN(NORMAL, logger, m, "Coder["<<coding<<"]="<<name<<": cwlTable[0.."<<numberOfCWLs-1<<"]=(");
00076             //m << "brutto CWL[bits]=(";
00077             for (unsigned int cwlIndex=0; cwlIndex<numberOfCWLs; ++cwlIndex){ m << config.get<int>("cwlTable",cwlIndex) << ","; }
00078             m << ")";
00079         MESSAGE_END();
00080 
00081         for (unsigned int cwlIndex=0; cwlIndex<numberOfCWLs; ++cwlIndex) {
00082             int CWL = config.get<int>("cwlTable",cwlIndex);
00083             //MESSAGE_SINGLE(NORMAL, logger, "Working on CWL:  "<<CWL);
00084             codeWordLengths.push_back(CWL); //codeWordLengths[cwlIndex] = CWL;
00085             assure(codeWordLengths[cwlIndex] == CWL, "CWL problem");
00086         }
00087         assure(codeWordLengths.size() == numberOfCWLs, "invalid codeWordLengths");
00088         //CodeWordLengths codeWordLengths; // codeWordLengths[0..5]={300,600,...}
00089         std::sort(codeWordLengths.begin(),codeWordLengths.end());
00090         //MESSAGE_BEGIN(NORMAL, logger, m, " - codeWordLengths=(");
00091         //    for (unsigned int cwlIndex=0; cwlIndex<numberOfCWLs; ++cwlIndex){ m << codeWordLengths[cwlIndex] << ",";  }
00092         //    m << ")";
00093         //MESSAGE_END();
00094 
00095         //SizeRegistry sizeRegistry; // member
00096         for (unsigned int cwlIndex=0; cwlIndex<numberOfCWLs; ++cwlIndex){
00097             int CWL = codeWordLengths[cwlIndex];
00098             //MESSAGE_SINGLE(VERBOSE, logger, " - Reading table for CWL=" << CWL );
00099             assure(config.knows("sizeRegistry["+wns::Ttos(CWL)+"]"),"PyConfig: missing: "<<"sizeRegistry["<<CWL<<"]");
00100             unsigned int tableSize = config.len("sizeRegistry["+wns::Ttos(CWL)+"]");
00101             MESSAGE_SINGLE(VERBOSE, logger, " - Reading table for CWL="<<CWL<<": "<<tableSize<<" elements.");
00102             LookupTable table(tableSize); // temporary object
00103             for (unsigned int miIndex=0; miIndex<tableSize; ++miIndex) { // forall mi values
00104                 double perValue = config.get<double>("sizeRegistry["+wns::Ttos(CWL)+"]["+wns::Ttos(miIndex)+"][1]");
00105                 // the original tables often have ripple near per=1.0. Bad thing.
00106                 // mathematical correction to make function monotonously decreasing:
00107                 if (perValue>1.0) perValue=1.0;
00108                 int past=1;
00109                 while(((int)miIndex-past>=0) && (table[miIndex-past] < perValue)) {
00110                     table[miIndex-past]=perValue; past++;
00111                 }
00112                 table[miIndex] = perValue;
00113             } // forall mi values
00114             assure(table.size() == tableSize, "wrong size of table");
00115             //sizeRegistry.insert(CWL, table); // table is copied
00116             // better:
00117             vectorOfTablesByCWLSize.push_back(table); // table is copied
00118         } // forall CWLs
00119         //assure(sizeRegistry.size() == numberOfCWLs, "wrong size of sizeRegistry");
00120         assure(vectorOfTablesByCWLSize.size() == numberOfCWLs, "wrong size of vectorOfTablesByCWLSize");
00121     } // if not empty
00122 } // CoderFullSpecification::configure()
00123 
00124 unsigned int
00125 TableCoder::suitableCWL(unsigned int blockLength /* gross */) const
00126 {
00127     unsigned int distance = 0;
00128     unsigned int minDistance = INT_MAX;
00129     unsigned int result = 0;
00130     //MESSAGE_SINGLE(NORMAL, logger, "CoderFullSpecification::suitableCWL("<<blockLength<<")");
00131     assure(numberOfCWLs == codeWordLengths.size(), "invalid codeWordLengths");
00132     for (unsigned int cwlIndex=0; cwlIndex<numberOfCWLs; ++cwlIndex){
00133         unsigned int cwl = codeWordLengths.at(cwlIndex); // =codeWordLengths[cwlIndex]
00134         distance = cwl > blockLength ? cwl - blockLength : blockLength - cwl;
00135         if (distance<minDistance) {
00136             minDistance = distance;
00137             result = cwl;
00138         } else if (distance==minDistance) {
00139             // Use the smaller of two CWLs in case of doubt
00140             result = std::min( result, cwl );
00141         }
00142     }
00143     MESSAGE_SINGLE(NORMAL, logger, "CoderFullSpecification::suitableCWL("<<blockLength<<") = "<<result);
00144     return result;
00145 }
00146 
00147 unsigned int
00148 TableCoder::suitableCWLposition(unsigned int blockLength /* gross */) const
00149 {
00150     unsigned int distance = 0;
00151     unsigned int minDistance = INT_MAX;
00152     unsigned int resultCWL = 0;
00153     unsigned int resultCWLposition = 0;
00154     //MESSAGE_SINGLE(NORMAL, logger, "CoderFullSpecification::suitableCWL("<<blockLength<<")");
00155     assure(numberOfCWLs == codeWordLengths.size(), "invalid codeWordLengths");
00156     for (unsigned int cwlIndex=0; cwlIndex<numberOfCWLs; ++cwlIndex){
00157         unsigned int cwl = codeWordLengths.at(cwlIndex); // =codeWordLengths[cwlIndex]
00158         distance = cwl > blockLength ? cwl - blockLength : blockLength - cwl;
00159         //MESSAGE_SINGLE(NORMAL, logger, "CoderFullSpecification::suitableCWL("<<blockLength<<"): compare["<<cwlIndex<<"] with cwl="<<cwl);
00160         if (distance<minDistance) {
00161             minDistance = distance;
00162             resultCWL = cwl; resultCWLposition = cwlIndex;
00163         } else if (distance==minDistance) {
00164             // Use the smaller of two CWLs in case of doubt
00165             resultCWL = std::min( resultCWL, cwl );
00166         }
00167     }
00168     MESSAGE_SINGLE(NORMAL, logger, "CoderFullSpecification::suitableCWL("<<blockLength<<") = "<<resultCWL);
00169     return resultCWLposition;
00170 }
00171 
00172 const CodeWordLengths&
00173 TableCoder::getCWLvector() const
00174 {
00175     return codeWordLengths;
00176 }
00177 
00178 double
00179 TableCoder::mapMI2PER(double mi,
00180                       /* blockLength=payload[net], not CWL[gross] */
00181                       unsigned int blockLength) const
00182 {
00183     MESSAGE_SINGLE(NORMAL,logger,"CoderFullSpecification::mapMI2PER(mi="<<mi<<",bl="<<blockLength<<")");
00184     if (mi > (1.0 - 1e-6)) { return 0.0; } // mi=1.0 => no PER
00185 
00186     //unsigned int bruttobits = (unsigned int) ((1.0*blockLength) / getRate());
00187     unsigned int bruttobits = (unsigned int) ((1.0*blockLength) / rate); // member
00188 
00189     // We only have tables for discrete CWLs, so
00190     // method 1 is, to choose the next matching CWL in table:
00191     // try to find the best Matching Codeword Length
00192     //unsigned int CWL = suitableCWL(bruttobits);
00193     unsigned int CWLposition = suitableCWLposition(bruttobits);
00194     // method 2 would be a kind of interpolation (but never average PER values!!!)
00195 
00196     MESSAGE_BEGIN(NORMAL, logger, m, "Mapping for block: netto=");
00197     m << blockLength << " Bits, brutto="
00198       << bruttobits << " Bits, using table for CWL=" << codeWordLengths.at(CWLposition) << " Bits.";
00199     MESSAGE_END();
00200 
00201     // obtain lookup table for the best matching code word length
00202     //const LookupTable &table = sizeRegistry.find(CWL); // copy???
00203     assure(vectorOfTablesByCWLSize.size()>CWLposition,"invalid size");
00204     const LookupTable& table = vectorOfTablesByCWLSize[CWLposition];
00205     // ^ reference (faster, without copy)
00206 
00207     // round mi for lookup
00208     //int MI = int(1000.0*mi + 0.5); // implicit policy for the table
00209     //return table[MI];
00210     // NEW: interpolation:
00211     int MI1 = int(1000.0*mi);
00212     int MI2 = int(1000.0*mi)+1;
00213     double PER1= table[MI1];
00214     double PER2= table[MI2];
00215     double PER = PER1 + (PER2-PER1)*(mi*1000.0-(double)MI1); // linear interpolation
00216     return PER;
00217 } // CoderFullSpecification::mapMI2PER()
00218 
00219 double
00220 TableCoder::PER2MIB(double per, unsigned int blockLength /* smaller number (payload) */) const
00221 {
00222     if (per <= 0.0) { return 1.0; }
00223     if (per >= 1.0) { return 0.0; }
00224     unsigned int bruttobits = (unsigned int) ((1.0*blockLength) / rate); // member
00225     unsigned int CWLposition = suitableCWLposition(bruttobits);
00226     assure(vectorOfTablesByCWLSize.size()>CWLposition,"CWLposition out of bounds");
00227     const LookupTable& table = vectorOfTablesByCWLSize[CWLposition];
00228     const unsigned int tableSize=table.size();
00229     assure(tableSize>0,"empty table");
00230     unsigned int leftBracket=0;
00231     unsigned int rightBracket=tableSize-1;
00232     unsigned int currentPosition=tableSize*3/4; // good guess for mi tables
00233     double mi=1.0; // best case
00234     double leftPER  = table[leftBracket];
00235     double rightPER = table[rightBracket];
00236     double slope    = rightPER - leftPER; // always negative for MI2PER
00237     double riseOrFall = (slope>=0) ? 1.0 : -1.0;
00238     // successive approximation:
00239     while ( (rightBracket-leftBracket)>1 ) {
00240         double PER = table[currentPosition];
00241         //std::cout << "PER2MIB(): ["<<leftBracket<<","<<currentPosition<<","<<rightBracket<<"]: per=["<<leftPER<<","<<PER<<","<<rightPER<<"]" <<std::endl;
00242         if ( riseOrFall*(per-PER)>0 ) { // go right
00243             leftBracket = currentPosition;
00244             leftPER  = table[leftBracket];
00245         } else { // go left
00246             rightBracket = currentPosition;
00247             rightPER = table[rightBracket];
00248         }
00249         currentPosition = (rightBracket + leftBracket)/2; // middle
00250     }
00251     // linear interpolation:
00252     double  leftMI =  leftBracket/1000.0;
00253     double rightMI = rightBracket/1000.0;
00254     if (rightBracket==1000) { rightPER=0.0; } // few tables have >0 at the end which leads to errors
00255     double deltaPER = (per-leftPER)/(rightPER-leftPER);
00256     //MESSAGE_SINGLE(NORMAL, logger, "PER2MIB(per="<<per<<", blockLength="<<blockLength<<"): "<<leftMI<<"<=MI<="<<rightMI<<", leftPER="<<leftPER<<", rightPER="<<rightPER<<", deltaPER="<<deltaPER);
00257     assure(deltaPER>=0.0,"PER2MIB(per="<<per<<", blockLength="<<blockLength<<"): "<<leftMI<<"<=MI<="<<rightMI<<", leftPER="<<leftPER<<", rightPER="<<rightPER<<", deltaPER="<<deltaPER);
00258     assure(deltaPER<=1.0,"PER2MIB(per="<<per<<", blockLength="<<blockLength<<"): "<<leftMI<<"<=MI<="<<rightMI<<", leftPER="<<leftPER<<", rightPER="<<rightPER<<", deltaPER="<<deltaPER);
00259     mi = leftMI + (rightMI-leftMI)*deltaPER;
00260     return mi;
00261 }
00262 
00263 
00264 double
00265 FormulaCoder::mapMI2PER(double /*mi*/,
00266                         unsigned int /*blockLength*/) const
00267 {
00268     assure(false, "Currently No working implementation here");
00269     /*
00270     // by formula:
00271     ser = pow(10.0, serlog);
00272     spp = double(compound->getLengthInBits())
00273         /double(PHYTools::getBitsPerSymbol(phyMode));
00274     // FIXME: Wrongness because of truncation of the Symbols per Packet
00275     per=1-pow((1-ser),spp);
00276     */
00277     return 0.0;
00278 }
00279 
00280 double
00281 FormulaCoder::PER2MIB(double /*per*/, unsigned int /*blockLength*/) const
00282 {
00283     assure(false, "Currently No working implementation here");
00284     return 0.0;
00285 }
00286 
00287 /**************************************************************/
00288 
00290 CoderFullSpecification*
00291 getCoderSpec(const wns::pyconfig::View& config)
00292 {
00293     std::string coderSpecType = config.get<std::string>("nameInCoderSpecFactory");
00294     return CoderSpecFactory::creator(coderSpecType)->create(config);
00295 }
00296 
00297 CoderFullMapping::CoderFullMapping(const wns::pyconfig::View& config)
00298     : CoderMapping(config),
00299       logger(std::string("RISE"), std::string("CoderFullMapping"))
00300 {
00301     const std::string coderFullMapName("coderMap");
00302     //MESSAGE_SINGLE(NORMAL, logger, "CoderFullMapping::configure()");
00303     coderFullSpecVector.clear(); // empty vector
00304     //logger = config.get("logger");
00305 
00306     // read in all the tables for the different codeRates and codeWordSizes
00307     //assure(config.knows(""),"PyConfig: missing: ");
00308     //assure(config.knows("coderFullMapping"),"PyConfig: missing: coderFullMapping");
00309     // at this point, the config points to the contents of CoderFullMapping()
00310     assure(config.knows(coderFullMapName),"PyConfig: missing:"<<coderFullMapName);
00311     unsigned int numberOfCoders = config.len(coderFullMapName);
00312     MESSAGE_SINGLE(NORMAL, logger, "CoderFullMapping::configure(): Storing Mapping for "<<numberOfCoders<<" CodingSpecifications ");
00313 
00314     for (Coding coding=0u; coding<numberOfCoders; ++coding) {
00315     //for (int ii=0; ii<numberOfCoders; ++ii){
00316         //Coding coding = (Coding) ii; // both int
00317         //MESSAGE_SINGLE(NORMAL, logger, " - Index of CoderSpecification = "<<coding);
00318         assure(config.knows(coderFullMapName+"["+ wns::Ttos(coding) +"]"),"PyConfig: missing:"<<coderFullMapName<<"["<<wns::Ttos(coding)<<"]");
00319         wns::pyconfig::View coderSpecConfig = config.getView(coderFullMapName+"["+wns::Ttos(coding)+"]");
00320         // temporary object, copied into the container:
00321         CoderFullSpecification* coderFullSpecification = getCoderSpec(coderSpecConfig);
00322         //codeNameRegistry.insert(coding, coderFullSpecification); // copy object
00323         // better, new way:
00324         coderFullSpecVector.push_back(coderFullSpecification); // copy object
00325         // ^ same as coderFullSpecVector[coding] = coderFullSpecification;
00326         // inherited structure:
00327         //coderSpecificationVector.push_back(CoderSpecification(coderNum,rate,coderName));
00328     } // forall coders
00329     maxCodeIndex = numberOfCoders-1; // inherited
00330     MESSAGE_SINGLE(NORMAL, logger, "CoderFullMapping::configure(): Stored Mapping for "<<numberOfCoders<<" CodingSpecifications ");
00331 }
00332 
00333 CoderFullMapping::~CoderFullMapping()
00334 {
00335     while (!coderFullSpecVector.empty())
00336     {
00337         delete *(coderFullSpecVector.begin());
00338         coderFullSpecVector.erase(coderFullSpecVector.begin());
00339     }
00340 }
00341 
00342 
00343 bool
00344 CoderFullMapping::isConfigured() const
00345 {
00346     return !coderFullSpecVector.empty(); // true if not empty
00347 }
00348 
00349 const CoderFullSpecification&
00350 CoderFullMapping::getCoderFullSpecification(Coding c) const
00351 {
00352     assure(!coderFullSpecVector.empty(), "empty vector");
00353     assure(coderFullSpecVector.size()>c, "bad vector size");
00354     return *(coderFullSpecVector[c]);
00355 }
00356 
00357 
00358 double
00359 CoderFullMapping::mapMI2PER(double mi,
00360                             unsigned int blockLength, /* blockLength=payload, not CWL */
00361                             Coding coding) const
00362 {
00363     if (mi > (1.0 - 1e-6)) { return 0.0; } // mi=1.0 => no PER
00364     assure(!coderFullSpecVector.empty(), "empty vector");
00365     assure(isConfigured(), "object is not yet configured");
00366     assure(coderFullSpecVector.size()>coding, "bad vector size");
00367     //CoderFullSpecification coderFullSpecification = codeNameRegistry.find(coding);
00368     const CoderFullSpecification &coderFullSpecification = *(coderFullSpecVector[coding]);
00369     return coderFullSpecification.mapMI2PER(mi, blockLength);
00370 }
00371 
00372 double
00373 CoderFullMapping::PER2MIB(double per, unsigned int blockLength, Coding coding) const
00374 {
00375     assure(!coderFullSpecVector.empty(), "empty vector");
00376     assure(isConfigured(), "object is not yet configured");
00377     assure(coderFullSpecVector.size()>coding, "bad vector size");
00378     const CoderFullSpecification &coderFullSpecification = *(coderFullSpecVector[coding]);
00379     return coderFullSpecification.PER2MIB(per, blockLength);
00380 }
00381 
00382 
00383 /**************************************************************/
00384 
00385 // constructor
00386 GENERICM2P::GENERICM2P(const wns::pyconfig::View& config)
00387     : coderFullMapping(wns::service::phy::phymode::CoderFullMappingInterface::getCoderFullMapping(config.get("mi2per")))
00388 {
00389     assure(coderFullMapping,"undefined coderFullMapping");
00390 }
00391 
00392 double
00393 GENERICM2P::mapMI2PER(double mi,
00394                       unsigned int blockLength, /* blockLength=payload, not CWL */
00395                       Coding coding) const
00396 {
00397     assure(coderFullMapping,"undefined coderFullMapping");
00398     return coderFullMapping->mapMI2PER(mi, blockLength, coding);
00399 }
00400 
00401 

Generated on Fri May 25 03:31:58 2012 for openWNS by  doxygen 1.5.5