MC++
mcfunc.hpp
1 // Copyright (C) 2009-2013 Benoit Chachuat, Imperial College London.
2 // All Rights Reserved.
3 
4 #ifndef MC__MCFUNC_HPP
5 #define MC__MCFUNC_HPP
6 
7 #include <cmath>
8 #include <cfloat>
9 #include <sys/resource.h>
10 #include <sys/times.h>
11 
12 namespace mc
13 {
14 
15 enum{ ICUT = 0, ICONV, ICONC };
16 const double PI = 4.0*std::atan(1.0);
17 
18 inline double sign
19 ( const double x )
20 {
21  // Compute and return squared value
22  return( x>=0? 1.: -1. );
23 }
24 
25 inline double sqr
26 ( const double x )
27 {
28  // Return squared value
29  return x*x;
30 }
31 
32 inline double inv
33 ( const double x )
34 {
35  // Return inverse value
36  return 1./x;
37 }
38 
39 template <typename U> inline U bilin
40 ( const U&x, const U&y, const unsigned int N=0 )
41 {
42  // Return bilinear product
43  return x*y;
44 }
45 
46 inline double arh
47 ( const double x, const double a )
48 {
49  // Return arrehenius-like term
50  return std::exp( - a / x );
51 }
52 
53 inline double dsqr
54 ( const double x )
55 {
56  // CReturn derivatvie of squared value
57  return 2.*x;
58 }
59 
60 inline double xlog
61 ( const double x )
62 {
63  // Return x*log(x) term
64  return x*std::log( x );
65 }
66 
67 inline double monomial
68 (const unsigned int n, const double*x, const int*k)
69 {
70  // Return monomial term \sum_i pow( x[i], k[i] )
71  if( n == 0 ){
72  return 1.;
73  }
74  if( n == 1 ){
75  return std::pow( x[0], k[0] );
76  }
77  return std::pow( x[0], k[0] ) * monomial( n-1, x+1, k+1 );
78 }
79 
80 inline double fstep
81 ( const double x )
82 {
83  // Return forward unit step at 0
84  return ( x>=0? 1: 0. );
85 }
86 
87 inline double bstep
88 ( const double x )
89 {
90  // Return backward unit step at 0
91  return ( x>=0? 0: 1. );
92 }
93 
94 inline double max
95 ( const unsigned int n, const double*x )
96 {
97  // Return maximum term \max_i { x[i] }
98  if( n == 0 ) return 0.;
99  if( n == 1 ) return x[0];
100  return std::max( x[0], max( n-1, x+1 ));
101 }
102 
103 inline double min
104 ( const unsigned int n, const double*x )
105 {
106  // Return minimum term \min_i { x[i] }
107  if( n == 0 ) return 0.;
108  if( n == 1 ) return x[0];
109  return std::min( x[0], min( n-1, x+1 ));
110 }
111 
112 inline unsigned int argmin
113 ( const unsigned int n, const double*x )
114 {
115  // Return argmin term \argmin_i { x[i] }
116  if( n == 0 || !x ) return 0;
117  unsigned int minndx = 0;
118  double minval = x[0];
119  for( unsigned int j=1; j<n; j++ )
120  if( minval > x[j] ){ minval = x[j]; minndx = j; }
121  return minndx;
122 }
123 
124 inline unsigned int argmax
125 ( const unsigned int n, const double*x )
126 {
127  // Return argmax term \argmin_i { x[i] }
128  if( n == 0 || !x ) return 0;
129  unsigned int maxndx = 0;
130  double maxval = x[0];
131  for( unsigned int j=1; j<n; j++ )
132  if( maxval < x[j] ){ maxval = x[j]; maxndx = j; }
133  return maxndx;
134 }
135 
136 inline double ltcond
137 ( const double cond, const double expr1, const double expr2 )
138 {
139  // Return condition expression { expr1 if cond<=0; expr2 else }
140  return ( cond<=0? expr1: expr2 );
141 }
142 
143 inline double gtcond
144 ( const double cond, const double expr1, const double expr2 )
145 {
146  // Return condition expression { expr1 if cond>=0; expr2 else }
147  return ( cond>=0? expr1: expr2 );
148 }
149 
150 inline double mid
151 ( const double a, const double b, const double c )
152 {
153  // Return the mid value of three scalars; e.g., b if a <= b <= c
154  if(( b <= a && a <= c ) || ( c <= a && a <= b )) return a;
155  if(( a <= b && b <= c ) || ( c <= b && b <= a )) return b;
156  return c;
157 }
158 
159 inline double mid
160 ( const double CONV, const double CONC, const double CUT,
161  int &id )
162 {
163  // Return the mid value of three scalars CONV, CONC and CUT,
164  // knowing that CONV <= CONC
165  // If the argument <a>id</a> is unspecified (negative value),
166  // the function indicates which value is the mid using the
167  // enumeration enum{ ICUT = 0, ICONV, ICONC } defined abobe
168  // in the mc namespace
169  if( id < 0 ){
170  if ( CUT < CONV ) { id = ICONV; return CONV; }
171  else if ( CUT > CONC ) { id = ICONC; return CONC; }
172  else { id = ICUT; return CUT; }
173  }
174 
175  // If the argument <a>id</a> is specified (nonnegative value),
176  // the function simply returns the corresponding value, which
177  // is not necessarily the mid value
178  if ( id == ICONV ) return CONV;
179  else if ( id == ICUT ) return CUT;
180  else return CONC;
181 }
182 
183 inline double mid
184 ( const double *DCONV, const double *DCONC, const int k, const int id )
185 {
186  // Return the value corresponding to <a>id</a> if ICONV or ICONC;
187  // otherwise return 0
188  if ( id == ICONV ) return DCONV[k];
189  else if ( id == ICUT ) return 0.;
190  else return DCONC[k];
191 }
192 
193 inline double mid
194 ( const double *DCONV, const double *DCONC, const double *DCUT,
195  const int k, const int id )
196 {
197  // Return the value corresponding to <a>id</a>
198  if ( id == ICONV ) return DCONV[k];
199  else if ( id == ICUT ) return DCUT[k];
200  else return DCONC[k];
201 }
202 
203 inline double
204 machprec()
205 {
206  return DBL_EPSILON;
207 /*
208  static bool BTINY = false;
209  static double RTINY = 1.0;
210  if( BTINY ) return RTINY;
211 
212  double RONE = 1.0;
213  int cnt = 0;
214  while ( RONE + RTINY > RONE && cnt < 64 ){
215  RTINY /= 2.;
216  cnt++;
217  }
218  RTINY *= 2.;
219  BTINY = true;
220  return RTINY;
221 */
222 }
223 
224 inline bool
225 isequal
226 ( const double real1, const double real2, const double atol=machprec(),
227  const double rtol=machprec() )
228 {
229  // Test if two real values are within the same absolute and relative
230  // tolerances
231  double gap = std::fabs(real1-real2);
232  double ave = 0.5*std::fabs(real1+real2);
233  return( gap<atol+ave*rtol? true: false );
234 }
235 
236 inline double
237 time()
238 {
239  // Return current time [seconds]
240  struct rusage ruse;
241  getrusage (RUSAGE_SELF, &ruse);
242  return ((double)(ruse.ru_utime.tv_sec + ruse.ru_utime.tv_usec / 1e6));
243 }
244 
245 } // namespace mc
246 #endif