/* 
    This file is part of the ChemCon molecular mechanics 
    and molecular graphics program.

    Copyright (C) 1997-2002  Alexei Nikitin 

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "Performance.h"

#ifdef MM_WIN32
#include <windows.h>

struct  Test_Performance_imp
{
    DWORD                        shift_;

public:
    LARGE_INTEGER                frequency_;
    LARGE_INTEGER                count1_;
    LARGE_INTEGER                count2_;

    DWORD                        counts_;
    double                       seconds_;

    Test_Performance_imp();
};

static Test_Performance_imp Test_Performance_imp;

Test_Performance_imp::
Test_Performance_imp ()
: 
    counts_(0), shift_(0), seconds_(0.)
{
#ifndef __BORLANDC__
    count1_.HighPart = 0;
    count2_.HighPart = 0;
    count1_.LowPart  = 0;
    count2_.LowPart  = 0;
#else
    count1_.QuadPart = 0;
    count2_.QuadPart = 0;
#endif
    QueryPerformanceFrequency (&frequency_);

    if (frequency_.QuadPart == 0)
        throw "Hardware does not support "
              "a high-resolution performance counter.";

    Test_Performance::get_interval();
    Test_Performance::get_interval();
    shift_ = counts_;
    //shift_ = 0;
}

int  Test_Performance::
get_interval ()
{
    QueryPerformanceCounter (&Test_Performance_imp.count2_);

#ifndef __BORLANDC__
    if( Test_Performance_imp.count1_.HighPart == 0 &&
        Test_Performance_imp.count1_.LowPart == 0 )
          Test_Performance_imp.count1_ = Test_Performance_imp.count2_;
#else
    if( Test_Performance_imp.count1_.QuadPart == 0 )
      Test_Performance_imp.count1_ = Test_Performance_imp.count2_;
#endif
    else
    {
#ifndef __BORLANDC__
        Test_Performance_imp.counts_  =
                   Test_Performance_imp.count2_.LowPart -
                   Test_Performance_imp.count1_.LowPart -
                   Test_Performance_imp.shift_;
#else
        Test_Performance_imp.counts_  = (LONGLONG)(
                   Test_Performance_imp.count2_.QuadPart -
                   Test_Performance_imp.count1_.QuadPart -
                   Test_Performance_imp.shift_);
#endif
    }
    QueryPerformanceCounter (&Test_Performance_imp.count2_);
    Test_Performance_imp.count1_ = Test_Performance_imp.count2_;

    return Test_Performance_imp.counts_;
}

double  Test_Performance::
get_time ()
{
    static LARGE_INTEGER count;
    QueryPerformanceCounter (&count);
#ifndef __BORLANDC__
    return double(count.LowPart) / Test_Performance_imp.frequency_.LowPart;
#else
    return double(count.QuadPart) / Test_Performance_imp.frequency_.QuadPart;
#endif
}

int  Test_Performance::
get_frequency ()
{
#ifndef __BORLANDC__
    return (int)Test_Performance_imp.frequency_.LowPart;
#else
    return (int)Test_Performance_imp.frequency_.QuadPart;
#endif
}
  
#else   // UNIX
#include <sys/time.h>

int  Test_Performance::
get_interval ()
{
    static struct timeval time1, time2;
    gettimeofday (&time2, 0);
    int result = (time2.tv_sec - time1.tv_sec) * get_frequency () 
        + time2.tv_usec - time1.tv_usec;
    time1 = time2;
    return result;
}

double  Test_Performance::
get_time ()
{
    struct timeval time;
    gettimeofday (&time, 0);
    return time.tv_sec + double(time.tv_usec) / get_frequency ();
}

int  Test_Performance::
get_frequency ()
{
    return 1000000;
}
#endif

