1 // Copyright (C) 2005, 2010 International Business Machines and others.
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License.
4 //
5 // $Id$
6 //
7 // Authors:  Carl Laird, Andreas Waechter    IBM       2005-08-12
8 
9 #include "IpoptConfig.h"
10 #include "IpUtils.hpp"
11 
12 #ifdef HAVE_CSTDLIB
13 # include <cstdlib>
14 #else
15 # ifdef HAVE_STDLIB_H
16 #  include <stdlib.h>
17 # endif
18 #endif
19 
20 #ifdef HAVE_CMATH
21 # include <cmath>
22 #else
23 # ifdef HAVE_MATH_H
24 #  include <math.h>
25 # else
26 #  error "don't have header file for math"
27 # endif
28 #endif
29 
30 #ifdef HAVE_CFLOAT
31 # include <cfloat>
32 #else
33 # ifdef HAVE_FLOAT_H
34 #  include <float.h>
35 # endif
36 #endif
37 
38 #ifdef HAVE_CIEEEFP
39 # include <cieeefp>
40 #else
41 # ifdef HAVE_IEEEFP_H
42 #  include <ieeefp.h>
43 # endif
44 #endif
45 
46 #ifdef HAVE_CTIME
47 # include <ctime>
48 #else
49 # ifdef HAVE_TIME_H
50 #  include <time.h>
51 # else
52 #  error "don't have header file for time"
53 # endif
54 #endif
55 
56 #ifdef HAVE_CSTDIO
57 # include <cstdio>
58 //  The special treatment of vsnprintf on SUN has been suggsted by Lou
59 //  Hafer 2010/07/04
60 # if defined(HAVE_VSNPRINTF) && defined(__SUNPRO_CC)
61 namespace std
62 {
63 #  include <iso/stdio_c99.h>
64 }
65 # endif
66 #else
67 # ifdef HAVE_STDIO_H
68 #  include <stdio.h>
69 # else
70 #  error "don't have header file for stdio"
71 # endif
72 #endif
73 
74 #ifdef HAVE_CSTDARG
75 # include <cstdarg>
76 #else
77 # ifdef HAVE_STDARG_H
78 #  include <stdarg.h>
79 # else
80 #  error "don't have header file for stdarg"
81 # endif
82 #endif
83 
84 #include <limits>
85 
86 // The following code has been copied from CoinUtils' CoinTime
87 
88 /** 8< (BEGIN) ******************************** */
89 
90 #if defined(_MSC_VER)
91 // Turn off compiler warning about long names
92 #  pragma warning(disable:4786)
93 #else
94 // MacOS-X and FreeBSD needs sys/time.h
95 #if defined(__MACH__) || defined (__FreeBSD__)
96 #include <sys/time.h>
97 #endif
98 #if !defined(__MSVCRT__)
99 #include <sys/resource.h>
100 #endif
101 #endif
102 
103 //#############################################################################
104 
105 #if defined(_MSC_VER)
106 
107 #if 0 // change this to 1 if want to use the win32 API
108 #include <windows.h>
109 #ifdef small
110 /* for some unfathomable reason (to me) rpcndr.h (pulled in by windows.h) does a
111    '#define small char' */
112 #undef small
113 #endif
114 #define TWO_TO_THE_THIRTYTWO 4294967296.0
115 #define DELTA_EPOCH_IN_SECS  11644473600.0
116 inline double IpCoinGetTimeOfDay()
117 {
118   FILETIME ft;
119 
120   GetSystemTimeAsFileTime(&ft);
121   double t = ft.dwHighDateTime * TWO_TO_THE_THIRTYTWO + ft.dwLowDateTime;
122   t = t/10000000.0 - DELTA_EPOCH_IN_SECS;
123   return t;
124 }
125 #else
126 #include <sys/types.h>
127 #include <sys/timeb.h>
IpCoinGetTimeOfDay()128 inline double IpCoinGetTimeOfDay()
129 {
130   struct _timeb timebuffer;
131 #pragma warning(disable:4996)
132   _ftime( &timebuffer ); // C4996
133 #pragma warning(default:4996)
134   return timebuffer.time + timebuffer.millitm/1000.0;
135 }
136 #endif
137 
138 #else
139 
140 #include <sys/time.h>
141 
IpCoinGetTimeOfDay()142 inline double IpCoinGetTimeOfDay()
143 {
144   struct timeval tv;
145   gettimeofday(&tv, NULL);
146   return static_cast<double>(tv.tv_sec) + static_cast<double>(tv.tv_usec)/1000000.0;
147 }
148 
149 #endif // _MSC_VER
150 
151 /** 8< (END) ******************************** */
152 
153 namespace Ipopt
154 {
155 
IsFiniteNumber(Number val)156   bool IsFiniteNumber(Number val)
157   {
158 #ifdef COIN_C_FINITE
159     return (bool)COIN_C_FINITE(val);
160 #else
161 
162     return true;
163 #endif
164 
165   }
166 
IpRandom01()167   Number IpRandom01()
168   {
169 #ifdef HAVE_DRAND48
170     return Number(drand48());
171 #else
172 # ifdef HAVE_RAND
173     return Number(rand())/Number(RAND_MAX);
174 # else
175 #  ifdef HAVE_STD__RAND
176     return Number(std::rand())/Number(RAND_MAX);
177 #  else
178     /* this is a workaround for gcc 4.8.x, x >= 2, for which the test for rand() in our old configure does not work */
179 #   if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8 && __GNUC_PATCHLEVEL__ >= 2
180       return Number(rand())/Number(RAND_MAX);
181 #   else
182 #    error "don't have function for random number generator"
183 #   endif
184 #  endif
185 # endif
186 #endif
187   }
188 
IpResetRandom01()189   void IpResetRandom01()
190   {
191 #ifdef HAVE_DRAND48
192     srand48(1);
193 #else
194 # ifdef HAVE_RAND
195     srand(1);
196 # else
197 #  ifdef HAVE_STD__RAND
198     std::srand(1);
199 #  else
200 #   if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8 && __GNUC_PATCHLEVEL__ >= 2
201     srand(1);
202 #   else
203 #    error "don't have function for random number generator"
204 #   endif
205 #  endif
206 # endif
207 #endif
208   }
209 
210 
211   static double Wallclock_firstCall_ = -1.;
212 
213   // The following function were taken from CoinTime.hpp in COIN/Coin
CpuTime()214   Number CpuTime()
215   {
216     double cpu_temp;
217 #if defined(_MSC_VER) || defined(__MSVCRT__)
218 
219     unsigned int ticksnow;        /* clock_t is same as int */
220 
221     ticksnow = (unsigned int)clock();
222 
223     cpu_temp = (double)((double)ticksnow/CLOCKS_PER_SEC);
224 #else
225 
226     struct rusage usage;
227     getrusage(RUSAGE_SELF,&usage);
228     cpu_temp = (double)usage.ru_utime.tv_sec;
229     cpu_temp += 1.0e-6*((double) usage.ru_utime.tv_usec);
230 #endif
231 
232     return cpu_temp;
233   }
234 
SysTime()235   Number SysTime()
236   {
237     double sys_temp;
238 #if defined(_MSC_VER) || defined(__MSVCRT__)
239 
240     // not yet implemented for Windows
241     sys_temp = 0.;
242 #else
243 
244     struct rusage usage;
245     getrusage(RUSAGE_SELF,&usage);
246     sys_temp = (double)usage.ru_stime.tv_sec;
247     sys_temp += 1.0e-6*((double) usage.ru_stime.tv_usec);
248 #endif
249 
250     return sys_temp;
251   }
252 
WallclockTime()253   Number WallclockTime()
254   {
255     double callTime = IpCoinGetTimeOfDay();
256     if (Wallclock_firstCall_ == -1.) {
257       Wallclock_firstCall_ = callTime;
258     }
259     return callTime - Wallclock_firstCall_;
260   }
261 
Compare_le(Number lhs,Number rhs,Number BasVal)262   bool Compare_le(Number lhs, Number rhs, Number BasVal)
263   {
264     Number mach_eps = std::numeric_limits<Number>::epsilon();
265     return (lhs - rhs <= 10.*mach_eps*fabs(BasVal));
266   }
267 
Snprintf(char * str,long size,const char * format,...)268   int Snprintf(char* str, long size, const char* format, ...)
269   {
270 #if defined(HAVE_VSNPRINTF) && defined(__SUNPRO_CC)
271     std::va_list ap;
272 #else
273     va_list ap;
274 #endif
275     va_start(ap, format);
276     int ret;
277 #ifdef HAVE_VA_COPY
278     va_list apcopy;
279     va_copy(apcopy, ap);
280 # ifdef HAVE_VSNPRINTF
281 #  ifdef __SUNPRO_CC
282     ret = std::vsnprintf(str, size, format, apcopy);
283 #  else
284     ret = vsnprintf(str, size, format, apcopy);
285 #  endif
286 # else
287 #  ifdef HAVE__VSNPRINTF
288     ret = _vsnprintf(str, size, format, apcopy);
289 #  else
290     ret = vsprintf(str, format, apcopy);
291 #  endif
292     va_end(apcopy);
293 # endif
294 #else
295 # ifdef HAVE_VSNPRINTF
296 #  ifdef __SUNPRO_CC
297     ret = std::vsnprintf(str, size, format, ap);
298 #  else
299     ret = vsnprintf(str, size, format, ap);
300 #  endif
301 # else
302 #  ifdef HAVE__VSNPRINTF
303     ret = _vsnprintf(str, size, format, ap);
304 #  else
305     ret = vsprintf(str, format, ap);
306 #  endif
307 # endif
308 #endif
309     va_end(ap);
310     return ret;
311   }
312 
313 } //namespace Ipopt
314