/*

   Timing.c		Measuring Program running time

   This module contains functions for measuring program running time.

   Copyright (C) 2004, Wong Chi Kwong.

   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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef RUSAGE
#include <sys/resource.h>
#else
#ifdef TIME_BY_CLOCK
#include <time.h>
#else
#include <sys/time.h>
#endif
#endif

#include "Timing.h"

void asciiTime(const char *c){
	time_t now = time(NULL);
	fprintf(stderr, "\n%s\n%s", c, asctime(localtime(&now)));
}


double setStartTime() {

#ifdef RUSAGE

	double usertime, systime;
	struct rusage usage;

	getrusage(RUSAGE_SELF, &usage);

	usertime = (double)usage.ru_utime.tv_sec + (double)usage.ru_utime.tv_usec / 1000000.0;
	systime = (double)usage.ru_stime.tv_sec + (double)usage.ru_stime.tv_usec / 1000000.0;

	return(usertime + systime);

#else
#ifdef TIME_BY_CLOCK

	return (double)clock() / (double)CLOCKS_PER_SEC;

#else

	struct timeval tp;
	gettimeofday(&tp, NULL);
	return (double)tp.tv_sec + (double)tp.tv_usec / (double)1000000;

#endif
#endif

}

double getElapsedTime(double startTime) {

#ifdef RUSAGE

	double usertime, systime;
	struct rusage usage;

	getrusage(RUSAGE_SELF, &usage);

	usertime = (double)usage.ru_utime.tv_sec + (double)usage.ru_utime.tv_usec / 1000000.0;
	systime = (double)usage.ru_stime.tv_sec + (double)usage.ru_stime.tv_usec / 1000000.0;

	return (usertime + systime) - startTime;

#else
#ifdef TIME_BY_CLOCK

	return (double)clock() / (double)CLOCKS_PER_SEC - startTime;

#else

	struct timeval tp;
	gettimeofday(&tp, NULL);
	return (double)tp.tv_sec + (double)tp.tv_usec / (double)1000000 - startTime;

#endif
#endif

}

void printElapsedTime(FILE *file, const int printHour, const int printMin, const int printSec,
					  const int secNumberOfDecimal, const double seconds) {

	printElapsedTimeNoNewLine(file, printHour, printMin, printSec, 0, secNumberOfDecimal, seconds);
	fprintf(file, "\n");

}

void printElapsedTimeNoNewLine(FILE *file, const int printHour, const int printMin, const int printSec,
					  const int secMinPrintLength, const int secNumberOfDecimal, const double seconds) {

	int hour, min;
	double sec;
	char secondDisplay[8] = "%0.0f s";

	#ifdef DEBUG
	if (printHour && !printMin && printSec) {
		fprintf(stderr, "printElapsedTime(): Cannot skip minute only!\n");
		exit(1);
	}
	if (secNumberOfDecimal > 9) {
		fprintf(stderr, "printElapsedTime(): secNumberOfDecimal > 9!\n");
		exit(1);
	}
	#endif

	secondDisplay[1] = secondDisplay[1] + (char)secMinPrintLength;
	secondDisplay[3] = secondDisplay[3] + (char)secNumberOfDecimal;

	sec = seconds;
	min = (int)(seconds / 60);
	if (!printSec && printMin) {
		if (seconds - min * 60 >= 30) {
			min++;
		}
	}
	if (printMin) {
		sec -= min * 60;
	}

	hour = min / 60;
	if (!printMin) {
		min = hour * 60;
		if (min >= 30) {
			hour++;
		}
	}
	if (printHour) {
		min -= hour * 60;
	}

	if (printHour) {
        fprintf(file, "%d h ", hour);
	}
	if (printMin) {
		fprintf(file, "%d m ", min);
	}
	if (printSec) {
		fprintf(file, secondDisplay, sec);
	}

}

