MappingBase.cc

00001 #include "MappingBase.h"
00002 #include <assert.h>
00003 //---Dimension implementation-----------------------------
00004 
00005 const Dimension Dimension::time = Dimension::time_static();
00006 const Dimension Dimension::frequency = Dimension::frequency_static();
00007 
00008 int& Dimension::nextFreeID () {
00009   static int* nextID = new int(1);
00010   return *nextID;
00011 }
00012 
00013 Dimension::DimensionIDMap& Dimension::dimensionIDs() {
00014   //use "construct-on-first-use" idiom to ensure correct order of
00015   //static initialization
00016   static DimensionIDMap* dimIDs = new DimensionIDMap();
00017   return *dimIDs;
00018 }
00019 
00020 Dimension::DimensionNameMap& Dimension::dimensionNames() {
00021   //use "construct-on-first-use" idiom to ensure correct order of
00022   //static initialization
00023   static DimensionNameMap* names = new DimensionNameMap();
00024   return *names;
00025 }
00026 
00027 Dimension& Dimension::time_static() {
00028   //use "construct-on-first-use" idiom to ensure correct order of
00029   //static initialization
00030   static Dimension* time = new Dimension("time");
00031   return *time;
00032 }
00033 
00034 Dimension& Dimension::frequency_static() {
00035   static Dimension* freq = new Dimension("frequency");
00036   return *freq;
00037 }
00038 
00039 int Dimension::getDimensionID(const std::string& name)
00040 {
00041   //get static members one time during initialization
00042   static DimensionIDMap& dimensionIDs = Dimension::dimensionIDs();
00043   static int& nextFreeID = Dimension::nextFreeID();
00044   static DimensionNameMap& dimensionNames = Dimension::dimensionNames();
00045 
00046   DimensionIDMap::iterator it = dimensionIDs.lower_bound(name);
00047 
00048   if(it == dimensionIDs.end() || it->first != name){
00049     int newID = 0;
00050 
00051     //time gets its own id to make sure it has the smallest
00052     if(name == "time")
00053       newID = 0;
00054     else
00055       newID = nextFreeID++;
00056 
00057     it = dimensionIDs.insert(it, DimensionIDMap::value_type(name, newID));
00058     dimensionNames[newID] = name;
00059   }
00060 
00061   return it->second;
00062 }
00063 
00064 Dimension::Dimension(const std::string & name):
00065   id(getDimensionID(name)){}
00066 
00067 bool Dimension::operator ==(const Dimension & other) const
00068 {
00069   return id == other.id;
00070 }
00071 
00072 bool Dimension::operator <(const Dimension & other) const
00073 {
00074   return id < other.id;
00075 }
00076 
00077 //--DimensionSet implementation ----------------------
00078 const DimensionSet DimensionSet::timeDomain(Dimension::time_static());
00079 const DimensionSet DimensionSet::timeFreqDomain(Dimension::time_static(), Dimension::frequency_static());
00080 
00081 //--Argument implementation---------------------------
00082 
00083 Argument::Argument(simtime_t timeVal):
00084   time(timeVal), values(), count(0) {}
00085 
00086 Argument::Argument(const DimensionSet & dims, simtime_t timeVal):
00087   time(timeVal), values(), count(0)
00088 {
00089   DimensionSet::const_iterator it = dims.begin();
00090 
00091   assert((*it) == Dimension::time_static());
00092 
00093   it++;
00094   while(it != dims.end()) {
00095     values[count] = std::pair<Dimension, double>(*it, 0.0);
00096     count++;
00097     it++;
00098   }
00099 }
00100 
00101 simtime_t Argument::getTime() const
00102 {
00103   return time;
00104 }
00105 
00106 void Argument::setTime(simtime_t time)
00107 {
00108   this->time = time;
00109 }
00110 
00111 Argument::iterator Argument::find(const Dimension& dim){
00112   assert(!(dim == Dimension::time_static()));
00113 
00114   for(iterator it = begin(); it != end() && it->first <= dim; ++it){
00115     if(it->first == dim)
00116       return it;
00117   }
00118 
00119   return end();
00120 }
00121 Argument::const_iterator Argument::find(const Dimension& dim) const{
00122   assert(!(dim == Dimension::time_static()));
00123 
00124   for(const_iterator it = begin(); it != end() && it->first <= dim; ++it){
00125     if(it->first == dim)
00126       return it;
00127   }
00128 
00129   return end();
00130 }
00131 
00132 Argument::iterator Argument::lower_bound(const Dimension& dim){
00133   assert(!(dim == Dimension::time_static()));
00134 
00135   iterator it = begin();
00136   while(it != end() && it->first < dim)
00137     ++it;
00138 
00139   return it;
00140 }
00141 Argument::const_iterator Argument::lower_bound(const Dimension& dim) const{
00142   assert(!(dim == Dimension::time_static()));
00143 
00144   const_iterator it = begin();
00145   while(it != end() && it->first < dim)
00146     ++it;
00147 
00148   return it;
00149 }
00150 
00151 bool Argument::hasArgVal(const Dimension& dim) const{
00152   return find(dim) != end();
00153 }
00154 
00155 double Argument::getArgValue(const Dimension & dim) const
00156 {
00157   const_iterator it = find(dim);
00158 
00159   if(it == end())
00160     return double();
00161 
00162   return it->second;
00163 }
00164 
00165 void Argument::setArgValue(const Dimension & dim, double value)
00166 {
00167   assert(!(dim == Dimension::time_static()));
00168 
00169   insertValue(begin(), dim, value);
00170 }
00171 
00172 Argument::iterator Argument::insertValue(iterator pos, const Dimension& dim, double value, bool ignoreUnknown){
00173   while(pos != end() && !(dim < pos->first)){
00174 
00175     if(pos->first == dim){
00176       pos->second = value;
00177       return pos;
00178     }
00179     ++pos;
00180   }
00181 
00182   if(ignoreUnknown)
00183     return pos;
00184 
00185   if(pos == end()){
00186     count++;
00187     *pos = std::pair<Dimension, double>(dim, value);
00188   } else {
00189     count++;
00190     iterator tmpPos = pos;
00191     std::pair<Dimension, double> n = *tmpPos;
00192     *tmpPos = std::pair<Dimension, double>(dim, value);
00193     while(++tmpPos != end()){
00194       std::pair<Dimension, double> tmp = *tmpPos;
00195       *tmpPos = n;
00196       n = tmp;
00197     }
00198   }
00199 
00200   return pos;
00201 }
00202 
00203 void Argument::setArgValues(const Argument& o, bool ingoreUnknown){
00204   time = o.time;
00205 
00206   iterator pos = begin();
00207   for(const_iterator i = o.begin(); i != o.end(); i++){
00208     pos = insertValue(pos, i->first, i->second, ingoreUnknown);
00209   }
00210 }
00211 
00212 bool Argument::isSamePosition(const Argument & o) const
00213 {
00214   if(count < o.count){
00215     return false;
00216   }
00217 
00218   //if(fabs(time - o.time) > 0.000001){
00219   if(time != o.time){
00220     return false;
00221   }
00222 
00223   if(o.count == 0)
00224     return true;
00225 
00226   const_iterator itO = o.begin();
00227   const_iterator it = begin();
00228 
00229   while (it != end())
00230   {
00231     if (itO->first < it->first) {
00232       break;
00233     } else if (it->first < itO->first)
00234       ++it;
00235     else {
00236       //if((fabs(values[it].second - o.values[itO].second) > 0.000001)){
00237       if(it->second != itO->second){
00238         break;
00239       }
00240       ++it;
00241       ++itO;
00242     }
00243     if (itO == o.end()) return true;
00244   }
00245 
00246   return false;
00247 }
00248 
00249 bool Argument::isClose(const Argument& o, double epsilon) const{
00250   if(count != o.count)
00251     return false;
00252 
00253   if(fabs(time - o.time) > epsilon)
00254     return false;
00255 
00256   const_iterator itO = o.begin();
00257   for(const_iterator it = begin();
00258     it != end(); it++) {
00259 
00260     if(!(it->first == itO->first) || (fabs(it->second - itO->second) > epsilon)){
00261       return false;
00262     }
00263     itO++;
00264   }
00265 
00266   return true;
00267 }
00268 
00269 bool Argument::operator==(const Argument & o) const
00270 {
00271   if(count != o.count)
00272     return false;
00273 
00274   if(time != o.time)
00275     return false;
00276 
00277   const_iterator itO = o.begin();
00278   for(const_iterator it = begin();
00279     it != end(); it++) {
00280 
00281     if(!(it->first == itO->first) || (it->second != itO->second)){
00282       return false;
00283     }
00284     itO++;
00285   }
00286 
00287   return true;
00288 }
00289 
00290 void Argument::operator=(const Argument& o){
00291   count = o.count;
00292 
00293   memcpy(values, o.values, sizeof(std::pair<Dimension, double>) * count);
00294   //for(unsigned int i = 0; i < count; i++)
00295   //  values[i] = o.values[i];
00296 
00297   time = o.time;
00298 
00299 }
00300 
00301 bool Argument::operator<(const Argument & o) const
00302 {
00303   assert(getDimensions() == o.getDimensions());
00304 
00305   for(int it = (int)o.count - 1; it >= 0; --it){
00306     double diff = values[it].second - o.values[it].second;
00307     //if(fabs(diff) > 0.000001){
00308     if(diff != 0){
00309       return diff < 0.0;
00310     }
00311   }
00312 
00313   return (time - o.time) < 0;
00314 }
00315 
00316 double Argument::compare(const Argument& o, const DimensionSet& dims) const{
00317   DimensionSet::const_reverse_iterator rIt = dims.rbegin();
00318 
00319   int ind = (int)count - 1;
00320   int indO = (int)o.count - 1;
00321 
00322   //iterate through passed dimensions and compare arguments in these dimensions
00323   while(rIt != dims.rend()){
00324     const Dimension& dim = *rIt;
00325 
00326     //catch special case time (after which we can abort)
00327     if(dim == Dimension::time)
00328     {
00329       return SIMTIME_DBL(time - o.time);
00330     }
00331 
00332     //iterate indices to the passed dimensions or the next smaller
00333     while(ind >= 0 && dim < values[ind].first)
00334       --ind;
00335     while(indO >= 0 && dim < o.values[indO].first)
00336       --indO;
00337 
00338     //if the last dimensions could not be found compare the time
00339     if(ind < 0 || indO < 0)
00340     {
00341       return SIMTIME_DBL(time - o.time);
00342     }
00343 
00344     //if both Arguments are defined in the current dimensions
00345     //compare them (otherwise we assume them equal and continue)
00346     if(values[ind].first == dim && o.values[indO].first == dim){
00347       double diff = values[ind].second - o.values[indO].second;
00348 
00349       //if(fabs(diff) > 0.000001)
00350       if(diff != 0)
00351         return diff;
00352     }
00353     ++rIt;
00354   }
00355   return 0;
00356 }
00357 
00358 //---Mapping implementation---------------------------------------
00359 
00360 SimpleConstMappingIterator::SimpleConstMappingIterator(ConstMapping* mapping,
00361                const std::set<Argument>* keyEntries,
00362                const Argument& start):
00363   mapping(mapping),
00364   dimensions(mapping->getDimensionSet()),
00365   position(dimensions),
00366   keyEntries(keyEntries)
00367 {
00368   assert(keyEntries);
00369 
00370   //the passed start position should define a value for every dimension
00371   //of this iterators underlying mapping.
00372   assert(start.getDimensions().isSubSet(dimensions));
00373 
00374   //Since the position is compared to the key entries we have to make
00375   //sure it always contains only the dimensions of the underlying mapping.
00376   //(the passed Argument might have more dimensions)
00377   position.setArgValues(start, true);
00378 
00379   nextEntry = keyEntries->upper_bound(position);
00380 }
00381 
00382 SimpleConstMappingIterator::SimpleConstMappingIterator(ConstMapping* mapping,
00383                const std::set<Argument>* keyEntries):
00384   mapping(mapping),
00385   dimensions(mapping->getDimensionSet()),
00386   position(dimensions),
00387   keyEntries(keyEntries)
00388 {
00389   assert(keyEntries);
00390 
00391   jumpToBegin();
00392 }
00393 
00394 void SimpleConstMapping::createKeyEntries(const Argument& from, const Argument& to, const Argument& step, Argument& pos){
00395 
00396   //get iteration borders and steps
00397   simtime_t fromT = from.getTime();
00398   simtime_t toT = to.getTime();
00399   simtime_t stepT = step.getTime();
00400 
00401   //iterate over interval without the end of the interval
00402   for(simtime_t t = fromT; t < toT; t += stepT){
00403     //create key entry at current position
00404     pos.setTime(t);
00405     keyEntries.insert(pos);
00406   }
00407 
00408   //makes sure that the end of the interval becomes it own key entry
00409   pos.setTime(toT);
00410   keyEntries.insert(pos);
00411 }
00412 
00413 void SimpleConstMapping::createKeyEntries(const Argument& from, const Argument& to, const Argument& step,
00414             DimensionSet::const_iterator curDim, Argument& pos){
00415   //get the dimension to iterate over
00416   Dimension d = *curDim;
00417 
00418   //increase iterator to next dimension (means curDim now stores the next dimension)
00419   --curDim;
00420   bool nextIsTime = (*curDim == Dimension::time);
00421 
00422   //get our iteration borders and steps
00423   double fromD = from.getArgValue(d);
00424   double toD = to.getArgValue(d);
00425   double stepD = step.getArgValue(d);
00426 
00427   //iterate over interval without the last entry
00428   for(double i = fromD; (i - toD) < -0.0001; i += stepD){
00429     pos.setArgValue(d, i); //update position
00430 
00431     //call iteration over sub dimension
00432     if(nextIsTime){
00433       createKeyEntries(from, to, step, pos);
00434     } else {
00435       createKeyEntries(from, to, step, curDim, pos);
00436     }
00437   }
00438 
00439   //makes sure that the end of the interval has its own key entry
00440   pos.setArgValue(d, toD);
00441   if(nextIsTime){
00442     createKeyEntries(from, to, step, pos);
00443   } else {
00444     createKeyEntries(from, to, step, curDim, pos);
00445   }
00446 }
00447 
00448 void SimpleConstMapping::initializeArguments(const Argument& min,
00449              const Argument& max,
00450              const Argument& interval) {
00451   keyEntries.clear();
00452   DimensionSet::const_iterator dimIt = dimensions.end();
00453   --dimIt;
00454   Argument pos = min;
00455   if(*dimIt == Dimension::time)
00456     createKeyEntries(min, max, interval, pos);
00457   else
00458     createKeyEntries(min, max, interval, dimIt, pos);
00459 }
00460 
00461 
00462 
00463 
00464