/* * This file is part of libcxxsupport. * * libcxxsupport is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libcxxsupport is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with libcxxsupport; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt * (DLR). */ /*! \file cxxutils.h * Various convenience functions used by the Planck LevelS package. * * Copyright (C) 2002 - 2010 Max-Planck-Society * \author Martin Reinecke \author Reinhard Hell */ #ifndef PLANCK_CXXUTILS_H #define PLANCK_CXXUTILS_H #include #include #include #include #include #include "error_handling.h" #include "datatypes.h" /*! \defgroup mathutilsgroup Mathematical helper functions */ /*! \{ */ /*! Returns \e true if | \a a-b | < \a epsilon * | \a b |, else \e false. */ template inline bool approx (F a, F b, F epsilon=1e-5) { using namespace std; return abs(a-b) < (epsilon*abs(b)); } /*! Returns \e true if | \a a-b | < \a epsilon, else \e false. */ template inline bool abs_approx (F a, F b, F epsilon=1e-5) { using namespace std; return abs(a-b) < epsilon; } /*! Returns the largest integer which is smaller than (or equal to) \a arg. */ template inline I ifloor (F arg) { using namespace std; return I(floor(arg)); } /*! Returns the integer which is nearest to \a arg. */ template inline I nearest (F arg) { return ifloor(arg+0.5); } /*! Returns \a v1+v2 if \a v1<0, \a v1-v2 if \a v1>=v2, else \a v1. \a v1 can be positive or negative; \a v2 must be positive. */ template inline T weak_modulo (T v1, T v2) { return (v1>=0) ? ((v1=0) ? ((v1 inline I imodulo (I v1, I v2) { I v=v1%v2; return (v>=0) ? v : v+v2; } /*! Returns -1 if \a signvalue is negative, else +1. */ template inline T sign (const T& signvalue) { return (signvalue>=0) ? 1 : -1; } /*! Returns \a val*pow(-1,m) */ template inline T xpow (I m, T val) { return (m&1) ? -val : val; } template struct isqrt_helper__ {}; template struct isqrt_helper__ { static uint32 isqrt (I arg) { using namespace std; return uint32 (sqrt(arg+0.5)); } }; template struct isqrt_helper__ { static uint32 isqrt (I arg) { using namespace std; long double arg2 = static_cast(arg)+0.5; return uint32 (sqrt(arg2)); } }; /*! Returns the integer \a n, which fulfills \a n*n<=arg<(n+1)*(n+1). */ template inline uint32 isqrt (I arg) { return isqrt_helper__4)>::isqrt(arg); } /*! Returns the largest integer \a n that fulfills \a 2^n<=arg. */ template inline unsigned int ilog2 (I arg) { unsigned int res=0; while (arg > 0x0000FFFF) { res+=16; arg>>=16; } if (arg > 0x000000FF) { res|=8; arg>>=8; } if (arg > 0x0000000F) { res|=4; arg>>=4; } if (arg > 0x00000003) { res|=2; arg>>=2; } if (arg > 0x00000001) { res|=1; } return res; } /*! Returns \a atan2(y,x) if \a x!=0 or \a y!=0; else returns 0. */ inline double safe_atan2 (double y, double x) { using namespace std; return ((x==0.) && (y==0.)) ? 0.0 : atan2(y,x); } /*! Helper function for linear interpolation (or extrapolation). The array must be ordered in ascending order; no two values may be equal. */ template inline void interpol_helper (const Iter &begin, const Iter &end, const T &val, Comp comp, tsize &idx, T &frac) { using namespace std; planck_assert((end-begin)>1,"sequence too small for interpolation"); idx = lower_bound(begin,end,val,comp)-begin; if (idx>0) --idx; idx = min(tsize(end-begin-2),idx); frac = (val-begin[idx])/(begin[idx+1]-begin[idx]); } /*! Helper function for linear interpolation (or extrapolation). The array must be ordered in ascending order; no two values may be equal. */ template inline void interpol_helper (const Iter &begin, const Iter &end, const T &val, tsize &idx, T &frac) { interpol_helper (begin,end,val,std::less(),idx,frac); } /*! \} */ template inline bool multiequal (const T &a, const T &b, const T &c) { return (a==b) && (a==c); } template inline bool multiequal (const T &a, const T &b, const T &c, const T &d) { return (a==b) && (a==c) && (a==d); } template inline bool multiequal (const T &a, const T &b, const T &c, const T &d, const T &e) { return (a==b) && (a==c) && (a==d) && (a==e); } template inline bool multiequal (const T &a, const T &b, const T &c, const T &d, const T &e, const T &f) { return (a==b) && (a==c) && (a==d) && (a==e) && (a==f); } template class IdxComp__ { private: It begin; Comp comp; public: IdxComp__ (It begin_, Comp comp_): begin(begin_), comp(comp_) {} bool operator() (std::size_t a, std::size_t b) const { return comp(*(begin+a),*(begin+b)); } }; /*! Performs an indirect sort on the supplied iterator range and returns in \a idx a \a vector containing the indices of the smallest, second smallest, third smallest, etc. element, according to \a comp. */ template inline void buildIndex (It begin, It end, std::vector &idx, Comp comp) { using namespace std; T2 num=end-begin; idx.resize(num); for (T2 i=0; i(begin,comp)); } /*! Performs an indirect sort on the supplied iterator range and returns in \a idx a \a vector containing the indices of the smallest, second smallest, third smallest, etc. element. */ template inline void buildIndex (It begin, It end, std::vector &idx) { using namespace std; typedef typename iterator_traits::value_type T; buildIndex(begin,end,idx,less()); } /*! Sorts the supplied iterator range according to the order given by \a idx. The operation is done out of place and requires temporary extra storage. */ template inline void sortByIndex (It begin, It end, const std::vector &idx) { using namespace std; typedef typename iterator_traits::value_type T; T2 num=end-begin; T *tmp= new T[num]; for (T2 i=0; i inline void sortByIndex_inplace (It begin, It end, const std::vector &idx) { using namespace std; typedef typename iterator_traits::value_type T; T2 num=end-begin; vector done(num,false); T2 cnt=0; while (cnt inline void indirectSort (It begin, It end, Comp comp) { using namespace std; typedef typename iterator_traits::value_type T; vector idx; buildIndex (begin,end,idx,comp); sortByIndex (begin,end,idx); } template inline void indirectSort (It begin, It end) { using namespace std; typedef typename iterator_traits::value_type T; indirectSort(begin,end,less()); } /*! \defgroup stringutilsgroup String handling helper functions */ /*! \{ */ /*! Returns the string \a orig without leading and trailing whitespace. */ std::string trim (const std::string &orig); /*! Returns a string containing the text representation of \a x. Care is taken that no information is lost in the conversion. */ template std::string dataToString(const T &x); template<> std::string dataToString (const bool &x); template<> std::string dataToString (const std::string &x); template<> std::string dataToString (const float &x); template<> std::string dataToString (const double &x); /*! Returns a string containing the text representation of \a x, padded with leading zeroes to \a width characters. */ std::string intToString(int64 x, tsize width); /*! Reads a value of a given datatype from a string */ template void stringToData (const std::string &x, T &value); template<> void stringToData (const std::string &x, std::string &value); template<> void stringToData (const std::string &x, bool &value); /*! Reads a value of a given datatype from a string */ template inline T stringToData (const std::string &x) { T result; stringToData(x,result); return result; } /*! Parses the file \a filename and returns the key/value pairs in \a dict. */ void parse_file (const std::string &filename, std::map &dict); /*! Case-insensitive string comparison Returns \a true, if \a a and \a b differ only in capitalisation, else \a false. */ bool equal_nocase (const std::string &a, const std::string &b); /*! Returns lowercase version of \a input. */ std::string tolower(const std::string &input); /*! \} */ /*! Prints a banner containing \a name, as well as some information about the source code and the parallelisation techniques enabled. */ void announce (const std::string &name); /*! Prints a banner containing \a name and checks if \a argc==argc_expected. If not, a usage description is given and the program is terminated. */ void module_startup (const std::string &name, int argc, const char **argv, int argc_expected, const std::string &argv_expected, bool verbose=true); /*! Divides the index range [\a glo; \a ghi) into \a nshares approximately equal parts, and returns the sub-range [\a lo; \a hi) of the part with the number \a myshare (first part has index 0). */ void calcShareGeneral (int64 glo, int64 ghi, int64 nshares, int64 myshare, int64 &lo, int64 &hi); /*! Helper class for dividing a range of work items into chunks of specified size. */ class chunkMaker { private: uint64 s_full, s_chunk, offset; public: /*! Creates an object that produces chunk information for \a s_full_ work items and a desired chunk size of \a s_chunk_. */ chunkMaker (uint64 s_full_, uint64 s_chunk_) : s_full(s_full_), s_chunk(s_chunk_), offset(0) {} /*! Returns the total number of chunks. */ uint64 nchunks() const { return (s_full+s_chunk-1)/s_chunk; } /*! Returns the start index of the next chunk in \a start, and its size in \a size. If all chunks have been processed already, the return value is \a false, else \a true. */ bool getNext (uint64 &start, uint64 &size) { using namespace std; if (offset>=s_full) return false; start=offset; size=min(s_chunk,s_full-offset); offset+=s_chunk; return true; } }; /*! Tries to split \a inp into a white-space separated list of values of type \a T, and appends them to \a list. */ template void split (const std::string &inp, std::vector &list); /*! Resizes \a container to zero and releases its memory. Typically used for std::vector. Taken from http://www.gotw.ca/gotw/054.htm */ template inline void releaseMemory (T &container) { T().swap(container); } /*! Releases all unused memory that \a container might have. Typically used for std::vector. Taken from http://www.gotw.ca/gotw/054.htm */ template inline void shrinkToFit (T &container) { T(container).swap(container); } /*! Breaks the string \a inp into tokens separated by \a delim, and returns them in \a list. */ void tokenize (const std::string &inp, char delim, std::vector &list); #endif