/*---------------------------------------------------------------------------*
 *                                   IT++			             *
 *---------------------------------------------------------------------------*
 * Copyright (c) 1995-2004 by Tony Ottosson, Thomas Eriksson, Pål Frenger,   *
 * Tobias Ringström, and Jonas Samuelsson.                                   *
 *                                                                           *
 * Permission to use, copy, modify, and distribute this software and its     *
 * documentation under the terms of the GNU General Public License is hereby *
 * granted. No representations are made about the suitability of this        *
 * software for any purpose. It is provided "as is" without expressed or     *
 * implied warranty. See the GNU General Public License for more details.    *
 *---------------------------------------------------------------------------*/

/*! 
  \file 
  \brief Implementation of Timing classes.
  \author Thomas Eriksson, Tony Ottosson, and Tobias Ringström

  1.10

  2004/08/06 02:12:22
*/

#include <ctime>
#include <iostream>
#ifdef __unix
#include <sys/time.h>
#endif
#ifdef _MSC_VER
#include <windows.h>
#endif

#include "base/timing.h"

using std::cout;
using std::endl;

namespace itpp { 

  //! Global object for tic and toc functions
  Real_Timer __tic_toc_timer; 

  //--------------------------------------------------------------------------------
  //	class Timer
  //--------------------------------------------------------------------------------
  Timer::Timer()
  {
    reset();
  }

  void Timer::start(void)
  {
    if (!running) {
      start_time = get_current_time();
      running = true;
    }
  }

  double Timer::stop(void)
  {
    if (running) {
      stop_time = get_current_time();
      elapsed_time += stop_time-start_time;
      running = false;
    }
    
    return elapsed_time;
  }

  void Timer::reset(double t)
  {
    elapsed_time = t;
    start_time = 0;
    stop_time = 0;
    running = false;
  }

  double Timer::get_time() const
  {
    return running ?
      elapsed_time + get_current_time()-start_time :
      elapsed_time;
  }

  void Timer::tic(void)
  {
    reset();
    start();
  }

  double Timer::toc(void)
  {
    return get_time() ;
  }

  void Timer::toc_print(void)
  {
    cout << "Elapsed time = " << get_time() << " seconds" << endl;
  }
  
  //--------------------------------------------------------------------------------
  //	class CPU_Timer
  //--------------------------------------------------------------------------------
  double CPU_Timer::get_current_time() const
  {
    return static_cast<double>(clock()) / CLOCKS_PER_SEC;
  }

  //--------------------------------------------------------------------------------
  //	class Real_Timer
  //--------------------------------------------------------------------------------
  double Real_Timer::get_current_time() const
  {
#ifdef MINGW
    // gettimeofday() is not defined in sys/time.h when compiling with MinGW.
    // time() only gives 1-sec accuracy instead of 1-microsec accuracy.
    return time(0);
#else
#ifdef __unix
    struct timeval t;
    gettimeofday(&t, 0);
    return t.tv_sec + t.tv_usec * 1.0e-6;
#else
    // Well done, Microsoft! (NOT!!!)
    // SYSTEMTIME st;
    FILETIME ft;
    // GetSystemTime(&st);
    // SystemTimeToFileTime(&st, &ft);
    GetSystemTimeAsFileTime(&ft);
    return ft.dwHighDateTime * 429.4967296 + ft.dwLowDateTime * 1.0e-7;
#endif
#endif
  }


  void tic()
  {
    __tic_toc_timer.tic();
  }

  double toc()
  {
    return __tic_toc_timer.toc();
  }

  void toc_print()
  {
    __tic_toc_timer.toc_print();
  }

  void pause(double t)
  {
	  if (t==-1) {
		  cout << "(Press enter to continue)" << endl ;
		  getchar();
	  } else {
		Real_Timer	T;
		T.start();
		while (T.get_time()<t);
	  }
  }
} //namespace itpp



syntax highlighted by Code2HTML, v. 0.9.1