1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2    Copyright (c) 2011-2021 The plumed team
3    (see the PEOPLE file at the root of the distribution for a list of names)
4 
5    See http://www.plumed.org for more information.
6 
7    This file is part of plumed, version 2.
8 
9    plumed is free software: you can redistribute it and/or modify
10    it under the terms of the GNU Lesser General Public License as published by
11    the Free Software Foundation, either version 3 of the License, or
12    (at your option) any later version.
13 
14    plumed is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU Lesser General Public License for more details.
18 
19    You should have received a copy of the GNU Lesser General Public License
20    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
21 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 #ifndef __PLUMED_tools_Tools_h
23 #define __PLUMED_tools_Tools_h
24 
25 #include "AtomNumber.h"
26 #include <vector>
27 #include <string>
28 #include <cctype>
29 #include <cstdio>
30 #include <cmath>
31 #include <limits>
32 #include <algorithm>
33 #include <sstream>
34 #include <memory>
35 
36 namespace PLMD {
37 
38 class IFile;
39 
40 /// \ingroup TOOLBOX
41 /// Very small non-zero number
42 const double epsilon(std::numeric_limits<double>::epsilon());
43 
44 /// \ingroup TOOLBOX
45 /// Boltzman constant in kj/K
46 const double kBoltzmann(0.0083144621);
47 
48 /// \ingroup TOOLBOX
49 /// PI
50 const double pi(3.141592653589793238462643383279502884197169399375105820974944592307);
51 
52 /// \ingroup TOOLBOX
53 /// Empty class which just contains several (static) tools
54 class Tools {
55 /// class to convert a string to a generic type T
56   template<class T>
57   static bool convertToAny(const std::string & str,T &t);
58 /// class to convert a string to a real type T.
59 /// T should be either float, double, or long double
60   template<class T>
61   static bool convertToReal(const std::string & str,T &t);
62 /// class to convert a string to a int type T
63   template<class T>
64   static bool convertToInt(const std::string & str,T &t);
65 public:
66 /// Split the line in words using separators.
67 /// It also take into account parenthesis. Outer parenthesis found are removed from
68 /// output, and the text between them is considered as a single word. Only the
69 /// outer parenthesis are processed, to allow nesting them.
70 /// parlevel, if not NULL, is increased or decreased according to the number of opened/closed parenthesis
71   static std::vector<std::string> getWords(const std::string & line,const char* sep=NULL,int* parlevel=NULL,const char* parenthesis="{", const bool& delete_parenthesis=true);
72 /// Get a line from the file pointer ifile
73   static bool getline(FILE*,std::string & line);
74 /// Get a parsed line from the file pointer ifile
75 /// This function already takes care of joining continued lines and splitting the
76 /// resulting line into an array of words
77   static bool getParsedLine(IFile&ifile,std::vector<std::string> & line, const bool trimcomments=true);
78 /// compare two string in a case insensitive manner
79   static bool caseInSensStringCompare(const std::string & str1, const std::string &str2);
80 /// Convert a string to a double, reading it
81   static bool convert(const std::string & str,double & t);
82 /// Convert a string to a long double, reading it
83   static bool convert(const std::string & str,long double & t);
84 /// Convert a string to a float, reading it
85   static bool convert(const std::string & str,float & t);
86 /// Convert a string to a int, reading it
87   static bool convert(const std::string & str,int & t);
88 /// Convert a string to a long int, reading it
89   static bool convert(const std::string & str,long int & t);
90 /// Convert a string to an unsigned int, reading it
91   static bool convert(const std::string & str,unsigned & t);
92 /// Convert a string to a long unsigned int, reading it
93   static bool convert(const std::string & str,long unsigned & t);
94 /// Convert a string to a atom number, reading it
95   static bool convert(const std::string & str,AtomNumber & t);
96 /// Convert a string to a string (i.e. copy)
97   static bool convert(const std::string & str,std::string & t);
98 /// Convert anything into a string
99   template<typename T>
100   static void convert(T i,std::string & str);
101 /// Remove trailing blanks
102   static void trim(std::string & s);
103 /// Remove trailing comments
104   static void trimComments(std::string & s);
105 /// Apply pbc for a unitary cell
106   static double pbc(double);
107 /// Retrieve a key from a vector of options.
108 /// It finds a key starting with "key=" or equal to "key" and copy the
109 /// part after the = on s. E.g.:
110 /// line.push_back("aa=xx");
111 /// getKey(line,"aa",s);
112 /// will set s="xx"
113   static bool getKey(std::vector<std::string>& line,const std::string & key,std::string & s,int rep=-1);
114 /// Find a keyword on the input line, eventually deleting it, and saving its value to val
115   template <class T>
116   static bool parse(std::vector<std::string>&line,const std::string&key,T&val,int rep=-1);
117 /// Find a keyword on the input line, eventually deleting it, and saving its value to a vector
118   template <class T>
119   static bool parseVector(std::vector<std::string>&line,const std::string&key,std::vector<T>&val,int rep=-1);
120 /// Find a keyword without arguments on the input line
121   static bool parseFlag(std::vector<std::string>&line,const std::string&key,bool&val);
122 /// Find a keyword on the input line, just reporting if it exists or not
123   static bool findKeyword(const std::vector<std::string>&line,const std::string&key);
124 /// Interpret atom ranges
125   static void interpretRanges(std::vector<std::string>&);
126 /// Remove duplicates from a vector of type T
127   template <typename T>
128   static void removeDuplicates(std::vector<T>& vec);
129 /// interpret ":" syntax for labels
130   static void interpretLabel(std::vector<std::string>&s);
131 /// list files in a directory
132   static std::vector<std::string> ls(const std::string&);
133 /// removes leading and trailing blanks from a string
134   static void stripLeadingAndTrailingBlanks( std::string& str );
135 /// Extract the extensions from a file name.
136 /// E.g.: extension("pippo.xyz")="xyz".
137 /// It only returns extensions with a length between 1 and 4
138 /// E.g.: extension("pippo.12345")="" whereas extenion("pippo.1234")="1234";
139 /// It is also smart enough to detect "/", so that
140 /// extension("pippo/.t")="" whereas extension("pippo/a.t")="t"
141   static std::string extension(const std::string&);
142 /// Fast int power
143   static double fastpow(double base,int exp);
144 /// Modified 0th-order Bessel function of the first kind
145   static double bessel0(const double& val);
146 /// Check if a string full starts with string start.
147 /// Same as full.find(start)==0
148   static bool startWith(const std::string & full,const std::string &start);
149   /**
150     Tool to create a vector of raw pointers from a vector of unique_pointers (const version).
151   Returning a vector is fast in C++11. It can be used in order to feed a vector<unique_ptr<T>>
152   to a function that takes a vector<T*>.
153   \verbatim
154   // some function that takes a vec
155   void func(std::vector<Data*> & vec);
156   std::vector<std::unique_ptr<Data>> vec;
157   // func(vec); // does not compile
158   func(Tools::unique2raw(vec)); // compiles
159   \endverbatim
160   Notice that the conversion is fast but takes
161   some time to allocate the new vector and copy the pointers. In case the function
162   acting on the vector<T*> is very fast and we do not want to add significant overhead,
163   it might be convenient to store a separate set of raw pointers.
164   \verbatim
165   // some function that takes a vec
166   void func(std::vector<Data*> & vec);
167   std::vector<std::unique_ptr<Data>> vec;
168 
169   // conversion done only once:
170   auto vec_ptr=Tools::unique2raw(vec);
171 
172   for(int i=0;i<1000;i++){
173     func(vec_ptr);
174   }
175   \endverbatim
176   */
177   template <typename T>
178   static std::vector<T*> unique2raw(const std::vector<std::unique_ptr<T>>&);
179 /// Tool to create a vector of raw pointers from a vector of unique_pointers.
180 /// See the non const version.
181   template <typename T>
182   static std::vector<const T*> unique2raw(const std::vector<std::unique_ptr<const T>>&);
183 /// Tiny class that changes directory and comes back when going out of scope.
184 /// In case system calls to change dir are not available it throws an exception.
185 /// \warning By construction, changing directory breaks thread safety! Use with care.
186   class DirectoryChanger {
187     static const size_t buffersize=4096;
188     char cwd[buffersize]= {0};
189   public:
190     explicit DirectoryChanger(const char*path);
191     ~DirectoryChanger();
192   };
193 };
194 
195 template <class T>
parse(std::vector<std::string> & line,const std::string & key,T & val,int rep)196 bool Tools::parse(std::vector<std::string>&line,const std::string&key,T&val,int rep) {
197   std::string s;
198   if(!getKey(line,key+"=",s,rep)) return false;
199   if(s.length()>0 && !convert(s,val))return false;
200   return true;
201 }
202 
203 template <class T>
parseVector(std::vector<std::string> & line,const std::string & key,std::vector<T> & val,int rep)204 bool Tools::parseVector(std::vector<std::string>&line,const std::string&key,std::vector<T>&val,int rep) {
205   std::string s;
206   if(!getKey(line,key+"=",s,rep)) return false;
207   val.clear();
208   std::vector<std::string> words=getWords(s,"\t\n ,");
209   for(unsigned i=0; i<words.size(); ++i) {
210     T v;
211     std::string s=words[i];
212     const std::string multi("@replicas:");
213     if(rep>=0 && startWith(s,multi)) {
214       s=s.substr(multi.length(),s.length());
215       std::vector<std::string> words=getWords(s,"\t\n ,");
216       plumed_assert(rep<static_cast<int>(words.size()));
217       s=words[rep];
218     }
219     if(!convert(s,v))return false;
220     val.push_back(v);
221   }
222   return true;
223 }
224 
225 template<typename T>
removeDuplicates(std::vector<T> & vec)226 void Tools::removeDuplicates(std::vector<T>& vec)
227 {
228   std::sort(vec.begin(), vec.end());
229   vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
230 }
231 
232 inline
parseFlag(std::vector<std::string> & line,const std::string & key,bool & val)233 bool Tools::parseFlag(std::vector<std::string>&line,const std::string&key,bool&val) {
234   for(auto p=line.begin(); p!=line.end(); ++p) {
235     if(key==*p) {
236       val=true;
237       line.erase(p);
238       return true;
239     }
240   }
241   return false;
242 }
243 
244 /// beware: this brings any number into a pbc that ranges from -0.5 to 0.5
245 inline
pbc(double x)246 double Tools::pbc(double x) {
247 #ifdef __PLUMED_PBC_WHILE
248   while (x>0.5) x-=1.0;
249   while (x<-0.5) x+=1.0;
250   return x;
251 #else
252   if(std::numeric_limits<int>::round_style == std::round_toward_zero) {
253     const double offset=100.0;
254     const double y=x+offset;
255     if(y>=0) return y-int(y+0.5);
256     else     return y-int(y-0.5);
257   } else if(std::numeric_limits<int>::round_style == std::round_to_nearest) {
258     return x-int(x);
259   } else return x-floor(x+0.5);
260 #endif
261 }
262 
263 template<typename T>
convert(T i,std::string & str)264 void Tools::convert(T i,std::string & str) {
265   std::ostringstream ostr;
266   ostr<<i;
267   str=ostr.str();
268 }
269 
270 inline
fastpow(double base,int exp)271 double Tools::fastpow(double base, int exp)
272 {
273   if(exp<0) {
274     exp=-exp;
275     base=1.0/base;
276   }
277   double result = 1.0;
278   while (exp)
279   {
280     if (exp & 1)
281       result *= base;
282     exp >>= 1;
283     base *= base;
284   }
285 
286   return result;
287 }
288 
289 template<typename T>
unique2raw(const std::vector<std::unique_ptr<T>> & x)290 std::vector<T*> Tools::unique2raw(const std::vector<std::unique_ptr<T>> & x) {
291   std::vector<T*> v(x.size());
292   for(unsigned i=0; i<x.size(); i++) v[i]=x[i].get();
293   return v;
294 }
295 
296 template<typename T>
unique2raw(const std::vector<std::unique_ptr<const T>> & x)297 std::vector<const T*> Tools::unique2raw(const std::vector<std::unique_ptr<const T>> & x) {
298   std::vector<const T*> v(x.size());
299   for(unsigned i=0; i<x.size(); i++) v[i]=x[i].get();
300   return v;
301 }
302 
303 }
304 
305 #endif
306 
307