00001 #ifndef Impala_Util_Iterable_h
00002 #define Impala_Util_Iterable_h
00003
00004 #include <math.h>
00005 #include "Util/StringParser.h"
00006
00007 namespace Impala {
00008 namespace Util {
00009
00010
00011 class Iterable
00012 {
00013 public:
00014 virtual int GetSteps() = 0;
00015 virtual void SetIteration(int i) = 0;
00016 virtual void Next() = 0;
00017 virtual double GetValue() = 0;
00018 virtual bool Done() = 0;
00019 virtual std::string GetName() = 0;
00020 virtual bool HasNotifications() const = 0;
00021 };
00022
00024
00025 class Param : public Iterable
00026 {
00027 public:
00028 Param(const std::string& name, double value):
00029 mName(name), mValue(value)
00030 {
00031 }
00032 virtual int GetSteps()
00033 {
00034 return 1;
00035 }
00036 virtual void SetIteration(int i)
00037 {
00038 }
00039 virtual void Next()
00040 {
00041 }
00042 virtual double GetValue()
00043 {
00044 return mValue;
00045 }
00046 virtual bool Done()
00047 {
00048 return true;
00049 }
00050 std::string GetName()
00051 {
00052 return mName;
00053 }
00054 virtual bool HasNotifications() const
00055 {
00056 return false;
00057 }
00058
00059 protected:
00060 std::string mName;
00061 double mValue;
00062 };
00063
00065 class Range : public Iterable
00066 {
00067 public:
00068 Range(const std::string& name, double start, double end, int steps, bool notifications):
00069 mName(name), mValue(start), mStart(start), mSteps(steps)
00070 {
00071 mIterator = 0;
00072 mRange = end - start;
00073 mHasNotifications = notifications;
00074 }
00075
00076 virtual int GetSteps()
00077 {
00078 return mSteps;
00079 }
00080 virtual void SetIteration(int i)
00081 {
00082 if(i<mSteps)
00083 mIterator = i;
00084 }
00085 virtual void Next()
00086 {
00087 mIterator++;
00088 }
00089 virtual bool Done()
00090 {
00091 return mIterator >= mSteps;
00092 }
00093 virtual double GetValue()
00094 {
00095 if(mSteps < 2)
00096 return mStart;
00097 return mStart+((mRange*mIterator)/(mSteps-1));
00098 }
00099
00100 std::string GetName()
00101 {
00102 return mName;
00103 }
00104 virtual bool HasNotifications() const
00105 {
00106 return mHasNotifications;
00107 }
00108 protected:
00109 std::string mName;
00110 double mValue;
00111 double mStart;
00112 double mRange;
00113 int mSteps;
00114 int mIterator;
00115 bool mHasNotifications;
00116 };
00117
00118
00120
00122 class LogRange : public Range
00123 {
00124 public:
00125 LogRange(const std::string& name, double startExp, double endExp, int steps, double logarithmicBase=10.0):
00126 Range(name, startExp, endExp, steps, false)
00127 {
00128 mLogarithmicBase = logarithmicBase;
00129 mValue = pow(mLogarithmicBase,startExp);
00130 }
00131
00132 double GetValue()
00133 {
00134 return pow(mLogarithmicBase, mStart + (double)mIterator*(mRange/(double)(mSteps-1)));
00135 }
00136 protected:
00137 double mLogarithmicBase;
00138 };
00139
00140
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 Iterable* ParseRangeDefinitionElement(const std::string& name, std::string& definition)
00196 {
00197 if(definition.find(':') == std::string::npos)
00198 return 0;
00199 bool logarithmic = false;
00200 double logarithmicBase = 10.0;
00201 if(definition.substr(0,3) == "log")
00202 {
00203 logarithmic = true;
00204 definition = definition.substr(3);
00205 logarithmicBase = 10.0;
00206 }
00207 if(definition.substr(0,4) == "2log")
00208 {
00209 logarithmic = true;
00210 definition = definition.substr(4);
00211 logarithmicBase = 2.0;
00212 }
00213 std::istringstream iss(definition);
00214 double start, stop;
00215 int steps;
00216 char c;
00217 iss >> start >> c >> stop;
00218 if(c!=':')
00219 {
00220 std::cout << "[ParseRangeDefinitionElement] error " << definition << " is not a valid element\n";
00221 return 0;
00222 }
00223 iss >> c;
00224 if(!iss.eof())
00225 {
00226 iss >> steps;
00227 if(c != '/')
00228 {
00229 std::cout << "[ParseRangeDefinitionElement] error " << definition << " is not a valid element\n";
00230 return 0;
00231 }
00232 }
00233 else
00234 steps = fabs(stop - start) + 1;
00235
00236 if(logarithmic)
00237 return new LogRange(name, start, stop, steps, logarithmicBase);
00238 return new Range(name, start, stop, steps, false);
00239 }
00240
00241 Iterable* ParseRangeDefinition(const std::string& name, const std::string& definition)
00242 {
00243 if(definition[0]!='[' || definition[definition.size()-1]!=']')
00244 {
00245 std::cout << "[ParseRangeDefinition] error " << definition << " is not a valid definition\n";
00246 return 0;
00247 }
00248 std::string inside = definition.substr(1,definition.size()-2);
00249 Iterable *it = ParseRangeDefinitionElement(name, inside);
00250 return it;
00251 }
00252
00253 bool IsRangeDefinition(std::string s)
00254 {
00255 if(s[0]!='[' || s[s.size()-1]!=']')
00256 return false;
00257 int left = 1;
00258 int right = s.size()-2;
00259 if(s.substr(left,3) == "log")
00260 left += 3;
00261 if(s.substr(left,4) == "2log")
00262 left += 4;
00263 std::istringstream iss(s.substr(left, right-left));
00264 double start, stop;
00265 char c1, c2;
00266 iss >> start >> c1 >> stop >> c2;
00267 if(c1 != ':')
00268 return false;
00269 if(!iss.eof())
00270 if(c2 != ':')
00271 return true;
00272 return true;
00273 }
00274
00275 }
00276 }
00277
00278 #endif //Impala_Util_Iterable_h