package Tools;

import java.text.*;

/**
 * A tool for inspecting the current process and wall-clock times. I
 * use it both for analyzing slow code and for running the experiments
 * in the {@link timingexp} package.
 */
public class Timer {
	long startTime[];
	long endTime[];
	boolean lapped;

	public Timer() {
		reset();
	}

	public void reset() {
		startTime = syscallTimes();
		endTime = null;
		lapped = false;
	}

	public void lap() {
		endTime = syscallTimes();
		lapped = true;
	}

	/**
	 * Use this method after reading out the time to continue timing
	 * from the same start point.
	 */
	public void unlap() {
		endTime = null;
		lapped = false;
	}

	public float getTime(int i) {
		if (!lapped) lap();
		return ((float)endTime[i]-startTime[i])/((float)startTime[clkTckOff]);
	}

	public double wallTime() {
		if (!lapped) lap();
		return (((double)endTime[wallSec]-startTime[wallSec])
			+(endTime[wallNsec]-startTime[wallNsec])/1000000000.0);
	}

	public String toString() {
		return getNF().format(wallTime())+" sec";
	}

	static NumberFormat nf=null;
	public static NumberFormat getNF() {
		if (nf==null) {
			nf = NumberFormat.getInstance();
			nf.setMaximumFractionDigits(3);
			nf.setMinimumFractionDigits(3);
		}
		return nf;
	}

	public float utime()	{ return getTime(utimeOff);		}
	public float stime()	{ return getTime(stimeOff);		}
	public float cutime()	{ return getTime(cutimeOff);	}
	public float cstime()	{ return getTime(cstimeOff);	}

	public static native long[] syscallTimes();
		// returns: [utime, stime, cutime, cstime, CLK_TCK]
	public static int utimeOff	= 0;
	public static int stimeOff	= 1;
	public static int cutimeOff	= 2;
	public static int cstimeOff	= 3;
	public static int clkTckOff	= 4;
	public static int wallSec	= 5;
	public static int wallNsec	= 6;

	static {
		System.loadLibrary("tools");
	}
}
