$treeview $search $mathjax
Palabos  Version 1.1
$projectbrief
$projectbrief
$searchbox

util.h

Go to the documentation of this file.
00001 /* This file is part of the Palabos library.
00002  *
00003  * Copyright (C) 2011 FlowKit Sarl
00004  * Avenue de Chailly 23
00005  * 1012 Lausanne, Switzerland
00006  * E-mail contact: contact@flowkit.com
00007  *
00008  * The most recent release of Palabos can be downloaded at 
00009  * <http://www.palabos.org/>
00010  *
00011  * The library Palabos is free software: you can redistribute it and/or
00012  * modify it under the terms of the GNU Affero General Public License as
00013  * published by the Free Software Foundation, either version 3 of the
00014  * License, or (at your option) any later version.
00015  *
00016  * The library is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU Affero General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Affero General Public License
00022  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00023 */
00024 
00029 #ifndef UTIL_H
00030 #define UTIL_H
00031 
00032 #include "core/globalDefs.h"
00033 #include "core/plbDebug.h"
00034 #include "core/runTimeDiagnostics.h"
00035 #include "core/plbTypenames.h"
00036 #include <algorithm>
00037 #include <string>
00038 #include <sstream>
00039 #include <cmath>
00040 #include <cstring>
00041 #include <utility>
00042 #include <vector>
00043 #include <set>
00044 #include <limits>
00045 
00046 namespace plb {
00047 
00048 namespace util {
00049 
00051 template<typename T>
00052 T sqr(T arg) {
00053     return arg*arg;
00054 }
00055 
00057 inline plint kronDelta(plint iA, plint iB) {
00058     if (iA == iB) return 1;
00059     else return 0;
00060 }
00061 
00062 
00063 
00065 
00072 inline bool boolIsEqual(bool val1, bool val2) {
00073     return ( (val1 && val2) || !(val1 || val2) );
00074 }
00075 
00077 template<typename T>
00078 plint roundToInt(T value) {
00079     return value>0 ?
00080                static_cast<plint>(value+(T)0.5) :
00081                static_cast<plint>(value-(T)0.5);
00082 }
00083 
00085 inline plint roundUp(plint value, plint step) {
00086     plint modulo = value % step;
00087     plint result = value-modulo;
00088     if (modulo>0) {
00089         result += step;
00090     }
00091     return result;
00092 }
00093 
00095 inline plint roundDown(plint value, plint step) {
00096     plint modulo = value % step;
00097     plint result = value-modulo;
00098     if (modulo<0) {
00099         result -= step;
00100     }
00101     return result;
00102 }
00103 
00104 inline double twoToThePower(int power) {
00105     switch(power) {
00106         case 0: return 1.;
00107         case 1: return 2.;
00108         case 2: return 4.;
00109         case 3: return 8.;
00110         case 4: return 16.;
00111         case 5: return 32.;
00112         case 6: return 64.;
00113         case 7: return 128.;
00114         case 8: return 256.;
00115         case -1: return 1./2.;
00116         case -2: return 1./4.;
00117         case -3: return 1./8.;
00118         case -4: return 1./16.;
00119         case -5: return 1./32.;
00120         case -6: return 1./64.;
00121         case -7: return 1./128.;
00122         case -8: return 1./256.;
00123         default: return pow(2., (double)power);
00124     }
00125 }
00126 
00127 template<typename T>
00128 std::string val2str(T val) {
00129     std::stringstream valstr;
00130     valstr << val;
00131     return valstr.str();
00132 }
00133 
00134 template<typename T1, typename T2>
00135 std::string val2str(T1 val1, T2 val2) {
00136     std::stringstream valstr;
00137     valstr << val1 << " " << val2;
00138     return valstr.str();
00139 }
00140 
00141 template<typename T1, typename T2, typename T3>
00142 std::string val2str(T1 val1, T2 val2, T3 val3) {
00143     std::stringstream valstr;
00144     valstr << val1 << " " << val2 << " " << val3;
00145     return valstr.str();
00146 }
00147 
00148 template<typename T>
00149 void str2val(std::string str, T& val) {
00150     std::stringstream stream(str);
00151     if (!(stream >> val)) {
00152         plbLogicError (
00153                 std::string("Could not convert string \"") + str +
00154                 std::string("\" to type ") +
00155                 std::string(NativeType<T>::getName()) );
00156     }
00157 }
00158 
00159 inline
00160 std::vector<std::string> split(std::string str) {
00161     std::stringstream stream(str);
00162     std::string buf;
00163     std::vector<std::string> result;
00164     while (stream>>buf) {
00165         result.push_back(buf);
00166     }
00167     return result;
00168 }
00169 
00170 template<typename T>
00171 std::string consume(std::string str, T& val) {
00172     std::vector<std::string> tokens = split(str);
00173     if (tokens.size()>=1) {
00174         str2val(tokens[0], val);
00175     }
00176     else {
00177         plbLogicError("Could not read value from empty string.");
00178     }
00179     std::string remaining;
00180     for (plint i=1; i<(plint)tokens.size(); ++i) {
00181         remaining += tokens[i];
00182         if (i != (plint)tokens.size()-1) {
00183             remaining += " ";
00184         }
00185     }
00186     return remaining;
00187 }
00188 
00189 template<typename T1, typename T2>
00190 std::string consume(std::string str, T1& val1, T2& val2) {
00191     std::vector<std::string> tokens = split(str);
00192     if (tokens.size()>=2) {
00193         str2val(tokens[0], val1);
00194         str2val(tokens[1], val2);
00195     }
00196     else {
00197         plbLogicError (
00198                 std::string("Could not read two values from string \"") + str +
00199                 std::string("\"") );
00200     }
00201     std::string remaining;
00202     for (plint i=2; i<(plint)tokens.size(); ++i) {
00203         remaining += tokens[i];
00204         if (i != (plint)tokens.size()-1) {
00205             remaining += " ";
00206         }
00207     }
00208     return remaining;
00209 }
00210 
00211 template<typename T1, typename T2, typename T3>
00212 std::string consume(std::string str, T1& val1, T2& val2, T3& val3) {
00213     std::vector<std::string> tokens = split(str);
00214     if (tokens.size()>=3) {
00215         str2val(tokens[0], val1);
00216         str2val(tokens[1], val2);
00217         str2val(tokens[2], val3);
00218     }
00219     else {
00220         plbLogicError (
00221                 std::string("Could not read three values from string \"") + str +
00222                 std::string("\"") );
00223     }
00224     std::string remaining;
00225     for (plint i=3; i<(plint)tokens.size(); ++i) {
00226         remaining += tokens[i];
00227         if (i != (plint)tokens.size()-1) {
00228             remaining += " ";
00229         }
00230     }
00231     return remaining;
00232 }
00233 
00234 inline std::string tolower(std::string arg) {
00235     std::string result(arg.size(), ' ');
00236     std::transform(arg.begin(), arg.end(), result.begin(), ::tolower);
00237     return result;
00238 }
00239 
00240 inline std::string toupper(std::string arg) {
00241     std::string result(arg.size(), ' ');
00242     std::transform(arg.begin(), arg.end(), result.begin(), ::toupper);
00243     return result;
00244 }
00245 
00246 
00248 
00255 template<typename T>
00256 class Buffer {
00257 public:
00259     Buffer()
00260         : bufferSize(0),
00261           data(0)
00262     { }
00264     Buffer(pluint bufferSize_)
00265         : bufferSize(bufferSize_),
00266           data(new T[bufferSize])
00267     { }
00268     Buffer(Buffer<T> const& rhs)
00269         : bufferSize(rhs.bufferSize),
00270           data(new T[bufferSize])
00271     {
00272         for (pluint iData=0; iData<bufferSize; ++iData) {
00273             data[iData] = rhs.data[iData];
00274         }
00275     }
00276     ~Buffer() {
00277         delete [] data;
00278     }
00280     Buffer<T>& operator=(Buffer<T> const& rhs) {
00281         Buffer<T> newBuffer(rhs);
00282         swap(newBuffer);
00283         return *this;
00284     }
00286     void swap(Buffer<T>& rhs) {
00287         std::swap(bufferSize, rhs.bufferSize);
00288         std::swap(data, rhs.data);
00289     }
00291     void resize(pluint newBufferSize) {
00292         if (newBufferSize > bufferSize) {
00293             Buffer<T> newBuffer(newBufferSize);
00294             for (pluint iData=0; iData<bufferSize; ++iData) {
00295                 newBuffer.data[iData] = data[iData];
00296             }
00297             swap(newBuffer);
00298         }
00299     }
00301     void reallocate(pluint newBufferSize) {
00302         if (newBufferSize > bufferSize) {
00303             Buffer<T> newBuffer(newBufferSize);
00304             swap(newBuffer);
00305         }
00306     }
00308     T* get() {
00309         return data;
00310     }
00312     T const* get() const {
00313         return data;
00314     }
00316     T& operator[](pluint index) {
00317         PLB_PRECONDITION( index<bufferSize );
00318         return data[index];
00319     }
00321     T const& operator[](pluint index) const {
00322         PLB_PRECONDITION( index<bufferSize );
00323         return data[index];
00324     }
00325     pluint size() const {
00326         return bufferSize;
00327     }
00328 private:
00329     pluint bufferSize;
00330     T* data;
00331 };
00332 
00333 inline void linearRepartition(plint x0, plint x1, plint nBlocks,
00334                               std::vector<std::pair<plint,plint> >& ranges)
00335 {
00336     PLB_PRECONDITION(nBlocks>0);
00337     plint totalSize = x1-x0+1;
00338     PLB_PRECONDITION( nBlocks<=totalSize );
00339     ranges.resize(nBlocks);
00340     plint basicLength = totalSize/nBlocks;
00341     plint currentPos=0;
00342     for (plint iRange=0; iRange<nBlocks; ++iRange) {
00343         plint currentLength = basicLength;
00344         if (iRange<totalSize%nBlocks) {
00345             ++currentLength;
00346         }
00347         ranges[iRange] = std::pair<plint,plint>(x0+currentPos, x0+currentPos+currentLength-1);
00348         currentPos+=currentLength;
00349     }
00350 }
00351 
00353 inline void extendVectorSize(std::vector<int>& vect, pluint fullSize) {
00354     pluint currentSize = vect.size();
00355     if (currentSize<fullSize) {
00356         vect.resize(fullSize);
00357         for (pluint i=currentSize; i<fullSize; ++i) {
00358             vect[i] = -1;
00359         }
00360     }
00361 }
00362 
00365 template<typename T>
00366 bool fpequal(T x, T y, T eps)
00367 {
00368     bool val;
00369 
00370     if (fabs(x) <= 2.0 * eps)
00371         x = 0.0;
00372 
00373     if (fabs(y) <= 2.0 * eps)
00374         y = 0.0;
00375 
00376     if (x == 0.0 || y == 0.0) {
00377         if (fabs(x - y) <= 2.0 * eps)
00378             val = true;
00379         else
00380             val = false;
00381     } else {
00382         if (fabs(x - y) <= eps * fabs(x) &&
00383             fabs(x - y) <= eps * fabs(y))
00384             val = true;
00385         else
00386             val = false;
00387     }
00388 
00389     return val;
00390 }
00391 
00395 template<typename T>
00396 bool fpequal_abs(T x, T y, T eps)
00397 {
00398     return fabs(x-y) <= eps;
00399 }
00400 
00401 class UniqueId {
00402 public:
00403     UniqueId() : currentId(0) { }
00404     id_t getId() {
00405         if (currentId==std::numeric_limits<id_t>::max()) {
00406             plbLogicError("Too many unique IDs requested.");
00407         }
00408         assignedIds.insert(currentId);
00409         return currentId++;
00410     }
00411     void releaseId(id_t id) {
00412         std::set<id_t>::iterator it = assignedIds.find(id);
00413         if (it==assignedIds.end()) {
00414             plbLogicError("Releasing a non-assigned ID.");
00415         }
00416         assignedIds.erase(it);
00417     }
00418 private:
00419     UniqueId(UniqueId const& rhs) { }
00420     UniqueId& operator=(UniqueId const& rhs) { return *this; }
00421 private:
00422     id_t currentId;
00423     std::set<id_t> assignedIds;
00424 };
00425 
00426 }  // namespace util
00427 
00428 }  // namespace plb
00429 
00430 #endif  // UTIL_H