00001 #ifndef FUNCTION_H_
00002 #define FUNCTION_H_
00003
00004 #include <omnetpp.h>
00005 #include <map>
00006 #include <set>
00007 #include <string>
00008 #include <algorithm>
00009 #include <assert.h>
00010 #include <FWMath.h>
00011
00012 #include "Interpolation.h"
00013
00014
00030 class Dimension {
00031 protected:
00033 typedef std::map<std::string, int>DimensionIDMap;
00035 typedef std::map<int, std::string>DimensionNameMap;
00036
00043 static DimensionIDMap& dimensionIDs();
00044
00051 static DimensionNameMap& dimensionNames();
00052
00059 static int& nextFreeID();
00060
00065 static int getDimensionID(const std::string& name);
00066
00068 int id;
00069
00070 protected:
00071
00072 public:
00075 static const Dimension time;
00076
00079 static const Dimension frequency;
00080
00081 public:
00082 Dimension():
00083 id(0)
00084 {}
00085
00090 Dimension(const std::string& name);
00091
00100 static Dimension& time_static();
00101
00110 static Dimension& frequency_static();
00111
00115 bool operator==(const Dimension& other) const;
00116
00123 bool operator<(const Dimension& other) const;
00124
00126 bool operator<=(const Dimension& other) const { return id <= other.id; }
00128 bool operator>(const Dimension& other) const { return id > other.id; }
00130 bool operator>=(const Dimension& other) const { return id >= other.id; }
00132 bool operator!=(const Dimension& other) const { return id != other.id; }
00133
00137 std::string getName() const{
00138 static DimensionNameMap& dimensionNames = Dimension::dimensionNames();
00139 return dimensionNames.find(id)->second;
00140 }
00141
00150 int getID() const { return id; }
00151
00153 friend std::ostream& operator<<(std::ostream& out, const Dimension& d) {
00154 return (out << d.getName() << "(" << d.id << ")");
00155 }
00156 };
00157
00173 class DimensionSet:public std::set<Dimension> {
00174 public:
00176 static const DimensionSet timeDomain;
00177
00179 static const DimensionSet timeFreqDomain;
00180 public:
00184 DimensionSet() {}
00185
00190 DimensionSet(const Dimension& d){
00191 this->insert(d);
00192 }
00197 DimensionSet(const Dimension& d1, const Dimension& d2){
00198 this->insert(d1);
00199 this->insert(d2);
00200 }
00205 DimensionSet(const Dimension& d1, const Dimension& d2, const Dimension& d3){
00206 this->insert(d1);
00207 this->insert(d2);
00208 this->insert(d3);
00209 }
00210
00219 bool isSubSet(const DimensionSet& other) const{
00220 if(this->size() < other.size())
00221 return false;
00222
00223 return std::includes(this->begin(), this->end(), other.begin(), other.end());
00224 }
00225
00235 bool isRealSubSet(const DimensionSet& other) const{
00236 if(this->size() <= other.size())
00237 return false;
00238
00239 return std::includes(this->begin(), this->end(), other.begin(), other.end());
00240 }
00241
00245 void addDimension(const Dimension& d) {
00246 this->insert(d);
00247 }
00248
00252 bool hasDimension(const Dimension& d) const{
00253 return this->count(d) > 0;
00254 }
00255
00259 bool operator==(const DimensionSet& o){
00260 if(size() != o.size())
00261 return false;
00262
00263 return std::equal(begin(), end(), o.begin());
00264 }
00265 };
00266
00279 class Argument{
00280 protected:
00281
00283 simtime_t time;
00284
00286 std::pair<Dimension, double> values[10];
00287
00289 unsigned int count;
00290
00291 public:
00293 typedef std::pair<Dimension, double>* iterator;
00295 typedef const std::pair<Dimension, double>* const_iterator;
00296
00297 protected:
00311 iterator insertValue(iterator pos, const Dimension& dim, double value, bool ignoreUnknown = false);
00312
00313 public:
00318 Argument(simtime_t timeVal = 0);
00319
00325 Argument(const DimensionSet& dims, simtime_t timeVal = 0);
00326
00330 simtime_t getTime() const;
00331
00335 void setTime(simtime_t time);
00336
00341 bool hasArgVal(const Dimension& dim) const;
00342
00352 double getArgValue(const Dimension& dim) const;
00353
00363 void setArgValue(const Dimension& dim, double value);
00364
00375 void setArgValues(const Argument& o, bool ignoreUnknown = false);
00376
00387 bool isSamePosition(const Argument& other) const;
00388
00393 bool operator==(const Argument& o) const;
00394
00400 bool isClose(const Argument& o, double epsilon = 0.000001) const;
00401
00415 bool operator<(const Argument& o) const;
00416
00428 double compare(const Argument& o, const DimensionSet& dims) const;
00429
00437 DimensionSet getDimensions() const {
00438 DimensionSet res(Dimension::time_static());
00439
00440 for(unsigned int i = 0; i < count; i++)
00441 res.addDimension(values[i].first);
00442
00443 return res;
00444 }
00445
00451 friend std::ostream& operator<<(std::ostream& out, const Argument& d) {
00452 out << "(" << d.time;
00453
00454 for(unsigned int i = 0; i < d.count; i++){
00455 out << ", " << d.values[i].second;
00456 }
00457 return (out << ")");
00458 }
00459
00464 void operator=(const Argument& o);
00465
00469 iterator begin() { return values; }
00473 const_iterator begin() const { return values; }
00474
00475
00479 iterator end() { return values + count; }
00483 const_iterator end() const { return values + count; }
00484
00490 iterator find(const Dimension& dim);
00496 const_iterator find(const Dimension& dim) const;
00497
00502 iterator lower_bound(const Dimension& dim);
00507 const_iterator lower_bound(const Dimension& dim) const;
00508 };
00509
00521 class NoNextIteratorException {};
00522
00543 class ConstMappingIterator {
00544 public:
00545 virtual ~ConstMappingIterator() {}
00546
00551 virtual const Argument& getNextPosition() const = 0;
00552
00558 virtual void jumpTo(const Argument& pos) = 0;
00559
00568 virtual void jumpToBegin() = 0;
00569
00576 virtual void iterateTo(const Argument& pos) = 0;
00577
00585 virtual void next() = 0;
00586
00594 virtual bool inRange() const = 0;
00595
00600 virtual bool hasNext() const = 0;
00601
00605 virtual const Argument& getPosition() const = 0;
00606
00614 virtual double getValue() const = 0;
00615 };
00616
00617 class Mapping;
00618
00630 class ConstMapping {
00631 protected:
00633 DimensionSet dimensions;
00634
00635 private:
00636 template<class T>
00637 std::string toString(T v, unsigned int length){
00638 char* tmp = new char[255];
00639 sprintf(tmp, "%.2f", v);
00640
00641 std::string result(tmp);
00642 delete[] tmp;
00643 while(result.length() < length)
00644 result += " ";
00645 return result;
00646 }
00647
00648 std::string toString(simtime_t v, unsigned int length){
00649 return toString(SIMTIME_DBL(v), length);
00650 }
00651
00652 public:
00653
00657 ConstMapping():
00658 dimensions(Dimension::time_static()) {}
00659
00666 ConstMapping(const DimensionSet& dimSet):
00667 dimensions(dimSet) {
00668
00669 assert(dimSet.hasDimension(Dimension::time_static()));
00670 }
00671
00672 virtual ~ConstMapping() {}
00673
00680 virtual double getValue(const Argument& pos) const = 0;
00681
00688 virtual ConstMappingIterator* createConstIterator() = 0;
00689
00696 virtual ConstMappingIterator* createConstIterator(const Argument& pos) = 0;
00697
00701 virtual ConstMapping* constClone() const = 0;
00702
00707 double operator[](const Argument& pos) const {
00708 return getValue(pos);
00709 }
00710
00714 const DimensionSet& getDimensionSet() const {
00715 return dimensions;
00716 }
00717
00724 template<class stream>
00725 void print(stream& out) {
00726 ConstMapping& m = *this;
00727 Dimension otherDim;
00728 const DimensionSet& dims = m.getDimensionSet();
00729 out << "Mapping domain: time";
00730 for(DimensionSet::iterator it = dims.begin(); it != dims.end(); ++it) {
00731 if(*it != Dimension::time){
00732 otherDim = *it;
00733 out << ", " << *it;
00734 }
00735 }
00736 out << endl;
00737
00738 ConstMappingIterator* it = m.createConstIterator();
00739
00740 if(!it->inRange()) {
00741 out << "Mapping is empty." << endl;
00742 return;
00743 }
00744
00745 Argument min = it->getPosition();
00746 Argument max = it->getPosition();
00747
00748 std::set<simtime_t> timePositions;
00749 std::set<double> otherPositions;
00750
00751 timePositions.insert(it->getPosition().getTime());
00752 if(dims.size() == 2){
00753 otherPositions.insert(it->getPosition().begin()->second);
00754 }
00755
00756 while(it->hasNext()) {
00757 it->next();
00758 const Argument& pos = it->getPosition();
00759
00760 min.setTime(std::min(min.getTime(), pos.getTime()));
00761 max.setTime(std::max(max.getTime(), pos.getTime()));
00762
00763 timePositions.insert(pos.getTime());
00764
00765 for(Argument::const_iterator itA = pos.begin(); itA != pos.end(); ++itA) {
00766 if(dims.size() == 2){
00767 otherPositions.insert(itA->second);
00768 }
00769 min.setArgValue(itA->first, std::min(min.getArgValue(itA->first), itA->second));
00770 max.setArgValue(itA->first, std::max(max.getArgValue(itA->first), itA->second));
00771 }
00772 }
00773 delete it;
00774
00775 if(dims.size() > 2) {
00776 out << "domain - min=" << min << " max=" << max << endl;
00777 return;
00778 }
00779
00780 out << "------+---------------------------------------------------------" << endl;
00781 out << "o\\t | ";
00782 std::set<simtime_t>::const_iterator tIt;
00783 for(tIt = timePositions.begin();
00784 tIt != timePositions.end(); ++tIt)
00785 {
00786 out << m.toString(*tIt * 1000, 6) << " ";
00787 }
00788 out << endl;
00789 out << "------+---------------------------------------------------------" << endl;
00790
00791 it = m.createConstIterator();
00792
00793
00794 if(dims.size() == 1) {
00795 out << "value" << " | ";
00796 while(it->inRange()) {
00797 out << m.toString(FWMath::mW2dBm(it->getValue()), 6) << " ";
00798
00799 if(!it->hasNext()) {
00800 break;
00801 }
00802 it->next();
00803 }
00804 } else {
00805 tIt = timePositions.begin();
00806 std::set<double>::const_iterator fIt = otherPositions.begin();
00807 out << m.toString(*fIt, 5) << " | ";
00808 while(it->inRange()) {
00809 if(*fIt != it->getPosition().getArgValue(otherDim)) {
00810 ++fIt;
00811 out << endl << m.toString(*fIt, 5) << " | ";
00812 tIt = timePositions.begin();
00813 assert(*fIt == it->getPosition().getArgValue(otherDim));
00814 }
00815
00816 while(*tIt < it->getPosition().getTime()){
00817 ++tIt;
00818 out << " ";
00819 }
00820
00821 out << m.toString(FWMath::mW2dBm(it->getValue()), 6) << " ";
00822
00823 if(!it->hasNext()) {
00824 break;
00825 }
00826 it->next();
00827 }
00828 }
00829 out << endl << "------+---------------------------------------------------------" << endl;
00830
00831 }
00832 };
00833
00834
00848 class MappingIterator:public ConstMappingIterator {
00849
00850 public:
00851 virtual ~MappingIterator() {}
00859 virtual void setValue(double value) = 0;
00860 };
00861
00862
00874 class Mapping:public ConstMapping {
00875 public:
00877 enum InterpolationMethod {
00879 STEPS,
00881 NEAREST,
00884 LINEAR
00885 };
00886
00887 protected:
00888
00889 public:
00890
00896 Mapping(const DimensionSet& dims):
00897 ConstMapping(dims) {}
00898
00902 Mapping():
00903 ConstMapping() {}
00904
00905 virtual ~Mapping() {}
00906
00913 virtual void setValue(const Argument& pos, double value) = 0;
00914
00928 virtual void appendValue(const Argument& pos, double value) {
00929 setValue(pos, value);
00930 }
00931
00936 virtual MappingIterator* createIterator() = 0;
00937
00944 virtual MappingIterator* createIterator(const Argument& pos) = 0;
00945
00952 virtual ConstMappingIterator* createConstIterator() {
00953 return createIterator();
00954 }
00955
00962 virtual ConstMappingIterator* createConstIterator(const Argument& pos) {
00963 return createIterator(pos);
00964 }
00965
00966
00967
00971 virtual Mapping* clone() const = 0;
00972
00977 virtual ConstMapping* constClone() const { return clone(); }
00978
00979
00980 };
00981
00982
00983
00984
00985
00986
01002 class SimpleConstMappingIterator:public ConstMappingIterator {
01003 protected:
01005 ConstMapping* mapping;
01006
01008 DimensionSet dimensions;
01009
01011 Argument position;
01012
01014 typedef std::set<Argument> KeyEntrySet;
01015
01019 const KeyEntrySet* keyEntries;
01020
01023 KeyEntrySet::const_iterator nextEntry;
01024
01025 public:
01034 SimpleConstMappingIterator(ConstMapping* mapping,
01035 const std::set<Argument>* keyEntries,
01036 const Argument& start);
01037
01045 SimpleConstMappingIterator(ConstMapping* mapping,
01046 const std::set<Argument>* keyEntries);
01047
01055 virtual const Argument& getNextPosition() const {
01056 if(nextEntry == keyEntries->end())
01057 throw NoNextIteratorException();
01058
01059 return *nextEntry;
01060 }
01061
01067 virtual void jumpTo(const Argument& pos) {
01068 position.setArgValues(pos, true);
01069 nextEntry = keyEntries->upper_bound(position);
01070 }
01071
01078 virtual void jumpToBegin(){
01079 nextEntry = keyEntries->begin();
01080
01081 if(nextEntry == keyEntries->end()) {
01082 position = Argument(dimensions);
01083 } else {
01084 position = *nextEntry;
01085 ++nextEntry;
01086 }
01087 }
01088
01098 virtual void iterateTo(const Argument& pos) {
01099 position.setArgValues(pos, true);
01100 while(nextEntry != keyEntries->end() && !(position < *nextEntry))
01101 ++nextEntry;
01102
01103 }
01104
01112 virtual void next() {
01113 if(nextEntry == keyEntries->end())
01114 throw NoNextIteratorException();
01115
01116 position = *nextEntry;
01117 ++nextEntry;
01118 }
01119
01127 virtual bool inRange() const {
01128 return !(keyEntries->empty()
01129 || (*(keyEntries->rbegin()) < position)
01130 || (position < *(keyEntries->begin())));
01131 }
01132
01138 virtual bool hasNext() const { return nextEntry != keyEntries->end(); }
01139
01145 virtual const Argument& getPosition() const { return position; }
01146
01154 virtual double getValue() const { return mapping->getValue(position); }
01155 };
01156
01176 class SimpleConstMapping:public ConstMapping {
01177 protected:
01179 typedef std::set<Argument> KeyEntrySet;
01180
01183 KeyEntrySet keyEntries;
01184
01185 protected:
01186
01191 void createKeyEntries(const Argument& from, const Argument& to, const Argument& step, Argument& pos);
01192
01197 void createKeyEntries(const Argument& from, const Argument& to, const Argument& step,
01198 DimensionSet::const_iterator curDim, Argument& pos);
01199
01200 public:
01207 virtual ConstMappingIterator* createConstIterator() {
01208 return new SimpleConstMappingIterator(this, &keyEntries);
01209 }
01210
01217 virtual ConstMappingIterator* createConstIterator(const Argument& pos) {
01218 return new SimpleConstMappingIterator(this, &keyEntries, pos);
01219 }
01220
01221 public:
01226 SimpleConstMapping(const DimensionSet& dims):
01227 ConstMapping(dims) {}
01228
01236 SimpleConstMapping(const DimensionSet& dims,
01237 const Argument& key):
01238 ConstMapping(dims){
01239
01240 initializeArguments(key);
01241 }
01242
01250 SimpleConstMapping(const DimensionSet& dims,
01251 const Argument& key1, const Argument& key2):
01252 ConstMapping(dims){
01253
01254 initializeArguments(key1, key2);
01255 }
01256
01264 SimpleConstMapping(const DimensionSet& dims,
01265 const Argument& min, const Argument& max, const Argument& interval):
01266 ConstMapping(dims){
01267
01268 initializeArguments(min, max, interval);
01269 }
01270
01277 void initializeArguments(const Argument& key){
01278 keyEntries.clear();
01279 keyEntries.insert(key);
01280 }
01281
01288 void initializeArguments(const Argument& key1, const Argument& key2){
01289 keyEntries.clear();
01290 keyEntries.insert(key1);
01291 keyEntries.insert(key2);
01292 }
01293
01301 void initializeArguments(const Argument& min,
01302 const Argument& max,
01303 const Argument& interval);
01304
01311 virtual double getValue(const Argument& pos) const = 0;
01312
01318 ConstMapping* constClone() const = 0;
01319 };
01320
01321
01322
01323
01324 #endif