1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*  Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB)                      */
7    	/*                                                                           */
8    	/*  Licensed under the Apache License, Version 2.0 (the "License");          */
9    	/*  you may not use this file except in compliance with the License.         */
10   	/*  You may obtain a copy of the License at                                  */
11   	/*                                                                           */
12   	/*      http://www.apache.org/licenses/LICENSE-2.0                           */
13   	/*                                                                           */
14   	/*  Unless required by applicable law or agreed to in writing, software      */
15   	/*  distributed under the License is distributed on an "AS IS" BASIS,        */
16   	/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17   	/*  See the License for the specific language governing permissions and      */
18   	/*  limitations under the License.                                           */
19   	/*                                                                           */
20   	/*  You should have received a copy of the Apache-2.0 license                */
21   	/*  along with SCIP; see the file LICENSE. If not visit scipopt.org.         */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	/**@file   clock.c
26   	 * @ingroup OTHER_CFILES
27   	 * @brief  methods for clocks and timing issues
28   	 * @author Tobias Achterberg
29   	 */
30   	
31   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32   	
33   	#include <assert.h>
34   	#if defined(_WIN32) || defined(_WIN64)
35   	#include <windows.h>
36   	#else
37   	#include <sys/times.h>
38   	#include <sys/time.h>
39   	#include <unistd.h>
40   	#endif
41   	#include <time.h>
42   	
43   	#include "scip/def.h"
44   	#include "scip/pub_message.h"
45   	#include "blockmemshell/memory.h"
46   	#include "scip/set.h"
47   	#include "scip/clock.h"
48   	
49   	#include "scip/struct_clock.h"
50   	
51   	/** converts CPU clock ticks into seconds */
52   	static
53   	SCIP_Real cputime2sec(
54   	   clock_t               cputime             /**< clock ticks for CPU time */
55   	   )
56   	{
57   	   clock_t clocks_per_second;
58   	
59   	#if defined(_WIN32) || defined(_WIN64)
60   	   clocks_per_second = 100;
61   	#else
62   	#ifndef CLK_TCK
63   	   clocks_per_second = sysconf(_SC_CLK_TCK);
64   	#else
65   	   clocks_per_second = CLK_TCK;
66   	#endif
67   	#endif
68   	
69   	   return (SCIP_Real)cputime / (SCIP_Real)clocks_per_second;
70   	}
71   	
72   	/*lint -esym(*,timeval)*/
73   	/*lint -esym(*,gettimeofday)*/
74   	
75   	/** converts wall clock time into seconds */
76   	static
77   	SCIP_Real walltime2sec(
78   	   long                  sec,                /**< seconds counter */
79   	   long                  usec                /**< microseconds counter */
80   	   )
81   	{
82   	   return (SCIP_Real)sec + 0.000001 * (SCIP_Real)usec;
83   	}
84   	
85   	/** converts seconds into CPU clock ticks */
86   	static
87   	void sec2cputime(
88   	   SCIP_Real             sec,                /**< seconds */
89   	   clock_t*              cputime             /**< pointer to store clock ticks for CPU time */
90   	   )
91   	{
92   	   clock_t clocks_per_second;
93   	
94   	   assert(cputime != NULL);
95   	
96   	#if defined(_WIN32) || defined(_WIN64)
97   	   clocks_per_second = 100;
98   	#else
99   	#ifndef CLK_TCK
100  	   clocks_per_second = sysconf(_SC_CLK_TCK);
101  	#else
102  	   clocks_per_second = CLK_TCK;
103  	#endif
104  	#endif
105  	   *cputime = (clock_t)(sec * clocks_per_second);
106  	}
107  	
108  	/** converts wall clock time into seconds */
109  	static
110  	void sec2walltime(
111  	   SCIP_Real             sec,                /**< seconds */
112  	   long*                 wallsec,            /**< pointer to store seconds counter */
113  	   long*                 wallusec            /**< pointer to store microseconds counter */
114  	   )
115  	{
116  	   assert(wallsec != NULL);
117  	   assert(wallusec != NULL);
118  	
119  	   *wallsec = (long)sec;
120  	   *wallusec = (long)((sec  - *wallsec) * 1000000.0);
121  	}
122  	
123  	
124  	/** sets the clock's type and converts the clock timer accordingly */
125  	static
126  	void clockSetType(
127  	   SCIP_CLOCK*           clck,               /**< clock timer */
128  	   SCIP_CLOCKTYPE        newtype             /**< new clock type */
129  	   )
130  	{
131  	   assert(clck != NULL);
132  	   assert(newtype != SCIP_CLOCKTYPE_DEFAULT);
133  	
134  	   if( clck->clocktype != newtype )
135  	   {
136  	      if( clck->clocktype == SCIP_CLOCKTYPE_DEFAULT )
137  	      {
138  	         assert(clck->nruns == 0);
139  	         clck->clocktype = newtype;
140  	         SCIPclockReset(clck);
141  	         SCIPdebugMessage("switched clock type to %d\n", newtype);
142  	      }
143  	      else
144  	      {
145  	         SCIP_Real sec;
146  	
147  	         sec = SCIPclockGetTime(clck);
148  	         clck->clocktype = newtype;
149  	         SCIPclockSetTime(clck, sec);
150  	         SCIPdebugMessage("switched clock type to %d (%g seconds -> %g seconds)\n", newtype, sec, SCIPclockGetTime(clck));
151  	      }
152  	   }
153  	}
154  	
155  	/** if the clock uses the default clock type and the default changed, converts the clock timer to the new type */
156  	static
157  	void clockUpdateDefaultType(
158  	   SCIP_CLOCK*           clck,               /**< clock timer */
159  	   SCIP_CLOCKTYPE        defaultclocktype    /**< default type of clock to use */
160  	   )
161  	{
162  	   assert(clck != NULL);
163  	   assert(defaultclocktype != SCIP_CLOCKTYPE_DEFAULT);
164  	
165  	   if( clck->usedefault && clck->clocktype != defaultclocktype )
166  	      clockSetType(clck, defaultclocktype);
167  	}
168  	
169  	/** creates a clock and initializes it */
170  	SCIP_RETCODE SCIPclockCreate(
171  	   SCIP_CLOCK**          clck,               /**< pointer to clock timer */
172  	   SCIP_CLOCKTYPE        clocktype           /**< type of clock */
173  	   )
174  	{
175  	   assert(clck != NULL);
176  	
177  	   SCIP_ALLOC( BMSallocMemory(clck) );
178  	
179  	   SCIPclockInit(*clck, clocktype);
180  	
181  	   return SCIP_OKAY;
182  	}
183  	
184  	/** frees a clock */
185  	void SCIPclockFree(
186  	   SCIP_CLOCK**          clck                /**< pointer to clock timer */
187  	   )
188  	{
189  	   assert(clck != NULL);
190  	
191  	   BMSfreeMemory(clck);
192  	}
193  	
194  	/** initializes and resets a clock */
195  	void SCIPclockInit(
196  	   SCIP_CLOCK*           clck,               /**< clock timer */
197  	   SCIP_CLOCKTYPE        clocktype           /**< type of clock */
198  	   )
199  	{
200  	   assert(clck != NULL);
201  	
202  	   SCIPdebugMessage("initializing clock %p of type %d\n", (void*)clck, clocktype);
203  	   clck->enabled = TRUE;
204  	   clck->lasttime = 0.0;
205  	   SCIPclockSetType(clck, clocktype);
206  	}
207  	
208  	/** completely stop the clock and reset the clock's counter to zero */
209  	void SCIPclockReset(
210  	   SCIP_CLOCK*           clck                /**< clock timer */
211  	   )
212  	{
213  	   assert(clck != NULL);
214  	
215  	   SCIPdebugMessage("resetting clock %p of type %d (usedefault=%u)\n", (void*)clck, clck->clocktype, clck->usedefault);
216  	   switch( clck->clocktype )
217  	   {
218  	   case SCIP_CLOCKTYPE_DEFAULT:
219  	      break;
220  	   case SCIP_CLOCKTYPE_CPU:
221  	      clck->data.cpuclock.user = 0;
222  	      break;
223  	   case SCIP_CLOCKTYPE_WALL:
224  	      clck->data.wallclock.sec = 0;
225  	      clck->data.wallclock.usec = 0;
226  	      break;
227  	   default:
228  	      SCIPerrorMessage("invalid clock type\n");
229  	      SCIPABORT();
230  	   }
231  	   clck->nruns = 0;
232  	}
233  	
234  	/** enables the clock */
235  	void SCIPclockEnable(
236  	   SCIP_CLOCK*           clck                /**< clock timer */
237  	   )
238  	{
239  	   assert(clck != NULL);
240  	
241  	   SCIPdebugMessage("enabling clock %p of type %d (usedefault=%u)\n", (void*)clck, clck->clocktype, clck->usedefault);
242  	
243  	   clck->enabled = TRUE;
244  	}
245  	
246  	/** disables and resets the clock */
247  	void SCIPclockDisable(
248  	   SCIP_CLOCK*           clck                /**< clock timer */
249  	   )
250  	{
251  	   assert(clck != NULL);
252  	
253  	   SCIPdebugMessage("disabling clock %p of type %d (usedefault=%u)\n", (void*)clck, clck->clocktype, clck->usedefault);
254  	
255  	   clck->enabled = FALSE;
256  	   SCIPclockReset(clck);
257  	}
258  	
259  	/** enables or disables \p clck, depending on the value of the flag */
260  	void SCIPclockEnableOrDisable(
261  	   SCIP_CLOCK*           clck,               /**< the clock to be disabled/enabled */
262  	   SCIP_Bool             enable              /**< should the clock be enabled? */
263  	   )
264  	{
265  	   assert(clck != NULL);
266  	
267  	   if( enable )
268  	      SCIPclockEnable(clck);
269  	   else
270  	      SCIPclockDisable(clck);
271  	}
272  	
273  	/** sets the type of the clock, overriding the default clock type, and resets the clock */
274  	void SCIPclockSetType(
275  	   SCIP_CLOCK*           clck,               /**< clock timer */
276  	   SCIP_CLOCKTYPE        clocktype           /**< type of clock */
277  	   )
278  	{
279  	   assert(clck != NULL);
280  	
281  	   SCIPdebugMessage("setting type of clock %p (type %d, usedefault=%u) to %d\n", 
282  	      (void*)clck, clck->clocktype, clck->usedefault, clocktype);
283  	
284  	   clck->clocktype = clocktype;
285  	   clck->usedefault = (clocktype == SCIP_CLOCKTYPE_DEFAULT);
286  	   SCIPclockReset(clck);
287  	}
288  	
289  	/** starts measurement of time in the given clock */
290  	void SCIPclockStart(
291  	   SCIP_CLOCK*           clck,               /**< clock timer */
292  	   SCIP_SET*             set                 /**< global SCIP settings */
293  	   )
294  	{
295  	   assert(clck != NULL);
296  	   assert(set != NULL);
297  	
298  	   if( set->time_enabled && clck->enabled )
299  	   {
300  	      clockUpdateDefaultType(clck, set->time_clocktype);
301  	
302  	      if( clck->nruns == 0 )
303  	      {
304  	#if defined(_WIN32) || defined(_WIN64)
305  	         FILETIME creationtime;
306  	         FILETIME exittime;
307  	         FILETIME kerneltime;
308  	         FILETIME usertime;
309  	#else
310  	         struct timeval tp; /*lint !e86*/
311  	         struct tms now;
312  	#endif
313  	
314  	         SCIPdebugMessage("starting clock %p (type %d, usedefault=%u)\n", (void*)clck, clck->clocktype, clck->usedefault);
315  	
316  	         switch( clck->clocktype )
317  	         {
318  	         case SCIP_CLOCKTYPE_CPU:
319  	#if defined(_WIN32) || defined(_WIN64)
320  	            GetProcessTimes(GetCurrentProcess(), &creationtime, &exittime, &kerneltime, &usertime);
321  	            clck->data.cpuclock.user -= usertime.dwHighDateTime * 42950 + usertime.dwLowDateTime / 100000L;
322  	#else
323  	            (void)times(&now);
324  	            clck->data.cpuclock.user -= now.tms_utime;
325  	#endif
326  	            clck->lasttime = cputime2sec(clck->data.cpuclock.user);
327  	            break;
328  	
329  	         case SCIP_CLOCKTYPE_WALL:
330  	#if defined(_WIN32) || defined(_WIN64)
331  	            clck->data.wallclock.sec -= time(NULL);
332  	#else
333  	            gettimeofday(&tp, NULL);
334  	            if( tp.tv_usec > clck->data.wallclock.usec ) /*lint !e115 !e40*/
335  	            {
336  	               clck->data.wallclock.sec -= (tp.tv_sec + 1); /*lint !e115 !e40*/
337  	               clck->data.wallclock.usec += (1000000 - tp.tv_usec); /*lint !e115 !e40*/
338  	            }
339  	            else
340  	            {
341  	               clck->data.wallclock.sec -= tp.tv_sec; /*lint !e115 !e40*/
342  	               clck->data.wallclock.usec -= tp.tv_usec; /*lint !e115 !e40*/
343  	            }
344  	#endif
345  	            clck->lasttime = walltime2sec(clck->data.wallclock.sec, clck->data.wallclock.usec);
346  	            break;
347  	
348  	         case SCIP_CLOCKTYPE_DEFAULT:
349  	         default:
350  	            SCIPerrorMessage("invalid clock type\n");
351  	            SCIPABORT();
352  	         }
353  	      }
354  	
355  	      clck->nruns++;
356  	   }
357  	}
358  	
359  	/** stops measurement of time in the given clock */
360  	void SCIPclockStop(
361  	   SCIP_CLOCK*           clck,               /**< clock timer */
362  	   SCIP_SET*             set                 /**< global SCIP settings */
363  	   )
364  	{
365  	   assert(clck != NULL);
366  	   assert(set != NULL);
367  	
368  	   if( set->time_enabled && clck->enabled )
369  	   {
370  	      assert(clck->nruns >= 1);
371  	
372  	      clck->nruns--;
373  	      if( clck->nruns == 0 )
374  	      {
375  	#if defined(_WIN32) || defined(_WIN64)
376  	         FILETIME creationtime;
377  	         FILETIME exittime;
378  	         FILETIME kerneltime;
379  	         FILETIME usertime;
380  	#else
381  	         struct timeval tp; /*lint !e86*/
382  	         struct tms now;
383  	#endif
384  	
385  	         SCIPdebugMessage("stopping clock %p (type %d, usedefault=%u)\n", (void*)clck, clck->clocktype, clck->usedefault);
386  	
387  	         switch( clck->clocktype )
388  	         {
389  	         case SCIP_CLOCKTYPE_CPU:
390  	#if defined(_WIN32) || defined(_WIN64)
391  	            GetProcessTimes(GetCurrentProcess(), &creationtime, &exittime, &kerneltime, &usertime);
392  	            clck->data.cpuclock.user += usertime.dwHighDateTime * 42950 + usertime.dwLowDateTime / 100000L;
393  	#else
394  	            (void)times(&now);
395  	            clck->data.cpuclock.user += now.tms_utime;
396  	#endif
397  	            break;
398  	
399  	         case SCIP_CLOCKTYPE_WALL:
400  	#if defined(_WIN32) || defined(_WIN64)
401  	            clck->data.wallclock.sec += time(NULL);
402  	#else
403  	            gettimeofday(&tp, NULL);
404  	            if( tp.tv_usec + clck->data.wallclock.usec > 1000000 ) /*lint !e115 !e40*/
405  	            {
406  	               clck->data.wallclock.sec += (tp.tv_sec + 1); /*lint !e115 !e40*/
407  	               clck->data.wallclock.usec -= (1000000 - tp.tv_usec); /*lint !e115 !e40*/
408  	            }
409  	            else
410  	            {
411  	               clck->data.wallclock.sec += tp.tv_sec; /*lint !e115 !e40*/
412  	               clck->data.wallclock.usec += tp.tv_usec; /*lint !e115 !e40*/
413  	            }
414  	#endif
415  	            break;
416  	
417  	         case SCIP_CLOCKTYPE_DEFAULT:
418  	         default:
419  	            SCIPerrorMessage("invalid clock type\n");
420  	            SCIPABORT();
421  	         }
422  	      }
423  	   }
424  	}
425  	
426  	/** returns whether the clock is currently running */
427  	SCIP_Bool SCIPclockIsRunning(
428  	   SCIP_CLOCK*           clck                /**< clock timer */
429  	   )
430  	{
431  	   assert(clck != NULL);
432  	
433  	   return (clck->nruns > 0);
434  	}
435  	
436  	
437  	/** gets the used time of this clock in seconds */
438  	SCIP_Real SCIPclockGetTime(
439  	   SCIP_CLOCK*           clck                /**< clock timer */
440  	   )
441  	{
442  	   SCIP_Real result;
443  	   assert(clck != NULL);
444  	   result = 0.0;
445  	
446  	   SCIPdebugMessage("getting time of clock %p (type %d, usedefault=%u, nruns=%d)\n",
447  	      (void*)clck, clck->clocktype, clck->usedefault, clck->nruns);
448  	
449  	   if( !clck->enabled )
450  	   {
451  	      result = 0.0;
452  	   }
453  	   else if( clck->nruns == 0 )
454  	   {
455  	      /* the clock is not running: convert the clocks timer into seconds */
456  	      switch( clck->clocktype )
457  	      {
458  	      case SCIP_CLOCKTYPE_DEFAULT:
459  	         break;
460  	      case SCIP_CLOCKTYPE_CPU:
461  	         result = cputime2sec(clck->data.cpuclock.user);
462  	         break;
463  	      case SCIP_CLOCKTYPE_WALL:
464  	         result = walltime2sec(clck->data.wallclock.sec, clck->data.wallclock.usec);
465  	         break;
466  	      default:
467  	         SCIPerrorMessage("invalid clock type\n");
468  	         SCIPABORT();
469  	         result = 0.0; /*lint !e527*/
470  	      }
471  	   }
472  	   else
473  	   {
474  	#if defined(_WIN32) || defined(_WIN64)
475  	      FILETIME creationtime;
476  	      FILETIME exittime;
477  	      FILETIME kerneltime;
478  	      FILETIME usertime;
479  	#else
480  	      struct timeval tp; /*lint !e86*/
481  	      struct tms now;
482  	#endif
483  	
484  	      /* the clock is currently running: we have to add the current time to the clocks timer */
485  	      switch( clck->clocktype )
486  	      {
487  	      case SCIP_CLOCKTYPE_CPU:
488  	#if defined(_WIN32) || defined(_WIN64)
489  	          GetProcessTimes(GetCurrentProcess(), &creationtime, &exittime, &kerneltime, &usertime);
490  	          result = cputime2sec(clck->data.cpuclock.user + usertime.dwHighDateTime * 42950 + usertime.dwLowDateTime / 100000L);
491  	#else
492  	         (void)times(&now);
493  	         result = cputime2sec(clck->data.cpuclock.user + now.tms_utime);
494  	#endif
495  	         break;
496  	      case SCIP_CLOCKTYPE_WALL:
497  	#if defined(_WIN32) || defined(_WIN64)
498  	         result = walltime2sec(clck->data.wallclock.sec + time(NULL), 0);
499  	#else
500  	         gettimeofday(&tp, NULL);
501  	         if( tp.tv_usec + clck->data.wallclock.usec > 1000000 ) /*lint !e115 !e40*/
502  	            result = walltime2sec(clck->data.wallclock.sec + tp.tv_sec + 1, /*lint !e115 !e40*/
503  	               (clck->data.wallclock.usec - 1000000) + tp.tv_usec); /*lint !e115 !e40*/
504  	         else
505  	            result = walltime2sec(clck->data.wallclock.sec + tp.tv_sec, /*lint !e115 !e40*/
506  	               clck->data.wallclock.usec + tp.tv_usec); /*lint !e115 !e40*/
507  	#endif
508  	         break;
509  	      case SCIP_CLOCKTYPE_DEFAULT:
510  	      default:
511  	         SCIPerrorMessage("invalid clock type\n");
512  	         SCIPABORT();
513  	         result = 0.0; /*lint !e527*/
514  	      }
515  	   }
516  	
517  	   /* time typically moves forward
518  	    * but when compiler optimizations meet fast CPUs, then rounding errors create small timetravel
519  	    */
520  	   assert(!EPSN(result, 1e-12));
521  	   if( result < 0.0 )
522  	      result = 0.0;
523  	
524  	   clck->lasttime = result;
525  	   return result;
526  	}
527  	
528  	/** gets the last validated time of this clock in seconds */
529  	SCIP_Real SCIPclockGetLastTime(
530  	   SCIP_CLOCK*           clck                /**< clock timer */
531  	   )
532  	{
533  	   assert(clck != NULL);
534  	
535  	   return clck->lasttime;
536  	}
537  	
538  	/** sets the used time of this clock in seconds */
539  	void SCIPclockSetTime(
540  	   SCIP_CLOCK*           clck,               /**< clock timer */
541  	   SCIP_Real             sec                 /**< time in seconds to set the clock's timer to */
542  	   )
543  	{
544  	   assert(clck != NULL);
545  	
546  	   SCIPdebugMessage("setting time of clock %p (type %d, usedefault=%u, nruns=%d) to %g\n",
547  	      (void*)clck, clck->clocktype, clck->usedefault, clck->nruns, sec);
548  	
549  	   /* if the clock type is not yet set, set it to an arbitrary value to be able to store the number */
550  	   if( clck->clocktype == SCIP_CLOCKTYPE_DEFAULT )
551  	      clockSetType(clck, SCIP_CLOCKTYPE_WALL);
552  	
553  	   switch( clck->clocktype )
554  	   {
555  	   case SCIP_CLOCKTYPE_CPU:
556  	      sec2cputime(sec, &clck->data.cpuclock.user);
557  	      break;
558  	
559  	   case SCIP_CLOCKTYPE_WALL:
560  	      sec2walltime(sec, &clck->data.wallclock.sec, &clck->data.wallclock.usec);
561  	      break;
562  	
563  	   case SCIP_CLOCKTYPE_DEFAULT:
564  	   default:
565  	      SCIPerrorMessage("invalid clock type\n");
566  	      SCIPABORT();
567  	   }
568  	
569  	   if( clck->nruns >= 1 )
570  	   {
571  	#if defined(_WIN32) || defined(_WIN64)
572  	      FILETIME creationtime;
573  	      FILETIME exittime;
574  	      FILETIME kerneltime;
575  	      FILETIME usertime;
576  	#else
577  	      struct timeval tp; /*lint !e86*/
578  	      struct tms now;
579  	#endif
580  	
581  	      /* the clock is currently running: we have to subtract the current time from the new timer value */
582  	      switch( clck->clocktype )
583  	      {
584  	      case SCIP_CLOCKTYPE_CPU:
585  	#if defined(_WIN32) || defined(_WIN64)
586  	         GetProcessTimes(GetCurrentProcess(), &creationtime, &exittime, &kerneltime, &usertime);
587  	         clck->data.cpuclock.user -= usertime.dwHighDateTime * 42950 + usertime.dwLowDateTime / 100000L;
588  	#else
589  	         (void)times(&now);
590  	         clck->data.cpuclock.user -= now.tms_utime;
591  	#endif
592  	         break;
593  	
594  	      case SCIP_CLOCKTYPE_WALL:
595  	#if defined(_WIN32) || defined(_WIN64)
596  	         clck->data.wallclock.sec -= time(NULL);
597  	#else
598  	         gettimeofday(&tp, NULL);
599  	         if( tp.tv_usec > clck->data.wallclock.usec ) /*lint !e115 !e40*/
600  	         {
601  	            clck->data.wallclock.sec -= (tp.tv_sec + 1); /*lint !e115 !e40*/
602  	            clck->data.wallclock.usec += (1000000 - tp.tv_usec); /*lint !e115 !e40*/
603  	         }
604  	         else
605  	         {
606  	            clck->data.wallclock.sec -= tp.tv_sec; /*lint !e115 !e40*/
607  	            clck->data.wallclock.usec -= tp.tv_usec; /*lint !e115 !e40*/
608  	         }
609  	#endif
610  	         break;
611  	
612  	      case SCIP_CLOCKTYPE_DEFAULT:
613  	      default:
614  	         SCIPerrorMessage("invalid clock type\n");
615  	         SCIPABORT();
616  	      }
617  	   }
618  	}
619  	
620  	/** gets current time of day in seconds (standard time zone) */
621  	SCIP_Real SCIPclockGetTimeOfDay(
622  	   void
623  	   )
624  	{
625  	#if defined(_WIN32) || defined(_WIN64)
626  	   time_t now;
627  	   now = time(NULL);
628  	   return (SCIP_Real)(now % (24*3600));
629  	#else
630  	   struct timeval tp; /*lint !e86*/
631  	
632  	   gettimeofday(&tp, NULL);
633  	
634  	   return (SCIP_Real)(tp.tv_sec % (24*3600)) + (SCIP_Real)tp.tv_usec / 1e+6; /*lint !e40 !e115*/
635  	#endif
636  	}
637