/* $Id: timer.c 820 2006-06-09 13:36:51Z olau $ */

#include "timer.h"

#ifdef DEBUG
#include <stdio.h>
#endif

TIMER _stopwatch;

#ifdef WIN32

/*****************/
/* Windows stuff */
/*****************/

#include <windows.h>

LONGLONG tickFreq = 0;

void initTimer(void) {
  LARGE_INTEGER freq;
  QueryPerformanceFrequency(&freq);
  tickFreq = freq.QuadPart;
#ifdef DEBUG
  printf("[initTimer] freq = %lld\n", tickFreq);
#endif
}

__inline
LONGLONG stopTimer(TIMER *t) {
  TIMER stop;
  QueryPerformanceCounter(&stop);
  stop.QuadPart -= t->QuadPart;
  if (tickFreq == 0)
    initTimer();
  if (tickFreq == 0)
    return 0;
  return (T_RESULT_RESOLUTION * stop.QuadPart) / tickFreq;
}

#else

/**************/
/* Unix stuff */
/**************/

/* used by startTimer() macro */
struct timezone tz = {0, 0};


/* convert struct timeval to unsigned long long
NOTE: LONGLONG is incompatible to ANSI-C
*/
LONGLONG
tv2l(TIMER *t) {
  return 1000000LL * (LONGLONG) t->tv_sec + (LONGLONG) t->tv_usec;
}


/* start timer */
inline void
startTimer(TIMER *t) {
  gettimeofday(t, &tz);
}


/* stop timer */
inline LONGLONG
stopTimer(TIMER *t) {
  TIMER start;
  start.tv_sec = t->tv_sec;
  start.tv_usec = t->tv_usec;
  gettimeofday(t, &tz);
  /* return result in microseconds */
  return tv2l(t) - tv2l(&start);
}

#endif /* WIN32 */

LONGLONG getTimerResolution(void)
{
  LONGLONG tbest = 2147483647;
  LONGLONG dt = 0;
  int i;

  for (i = 0; i < 1000; i++) {
    START();
    do {
      START();
      do {
        STOP(dt);
      }
      while (dt == 0);
#ifdef DEBUG
    printf("[getTimerResolution] Messung %3d: %lld µs\n", i+1, dt);
#endif
    }
    while (dt < 0); /* nochmal, falls Timer "gestolpert" ist */
    if (dt < tbest)
      tbest = dt;
  }
  return tbest;
}
