package gov.nist.androidsuite;

import android.annotation.SuppressLint;
import android.os.Debug;
import android.os.Environment;

@SuppressLint("DefaultLocale")
public class Val1 {
	/**
	 * val1.java 2013-05-29 3:17PM Reference executable for validating
	 * application profiling tools. val1: triangular distribution of time among
	 * N functions.
	 * 
	 * With default values of the parameters, the expected distribution of time
	 * (both self and total) is approximately function1 5x function2 4x
	 * function3 3x function4 2x function5 x main 0 for x = 6.67 %.
	 * 
	 * Old (2013-02-28 10:15) Spin was for Windows + Intel Composer XE 2013 +
	 * Microsoft Visual Studio 2012. Language c99.
	 * 
	 * New Spin for Android + DDMS + Eclipse. Language Java.
	 */

	// NUMFUN is not configurable in this spin of val1. NUMFUN is just a
	// constant according to the number of functions.
	private static final long NUMFUN = 5;

	// Configurable INNERLOOP: how many iterations in leaf functions.
	private long innerloop = 256;

	// Configurable OUTERLOOP: how many iterations in main program.
	private long outerloop = 256000 / innerloop;

	public String Output = "";

	private long accumulator = 1;
	private double adder = 0;
	private long loopmod;

	// / Method to start calling of functions
	public int Start(int repeat, boolean InReverse, long INNERLOOP,
			long OUTERLOOP, int TraceBuffer) {
		if (INNERLOOP > 0) {
			innerloop = INNERLOOP;
			outerloop = 256000 / innerloop;
		}
		if (OUTERLOOP > 0) {
			outerloop = OUTERLOOP;
		}

		if (InReverse) {
			Debug.startMethodTracing(Environment.getExternalStorageDirectory()+"/Traces/ValOne" + Integer.toString(repeat),
					TraceBuffer);
			reverseVal1();
		} else {
			Debug.startMethodTracing(Environment.getExternalStorageDirectory()+"/Traces/ValOne" + Integer.toString(repeat),
					TraceBuffer);
			normalVal1();
		}
		Debug.stopMethodTracing();
		String x = (InReverse) ? "yes" : "no";
		Output = "Accumulator: " + accumulator + "\n" + "Adder: " + adder
				+ "\n" + "Reverse: " + x;
		return 0;
	}

	// / Overload of the start function, if programmer just starts the gathering
	// process.
	public int Start() {
		// MainActivity.BufferToTrace is a variable being pass from the app
		// class,
		// if this class isn't available MainActivity.BufferToTrace default is
		// 8000000
		return Start(1, false, innerloop, outerloop, MainActivity.BufferToTrace);
	}

	// / Reversed val1
	private void reverseVal1() {
		for (long looper = 0; looper < outerloop; ++looper) {
			loopmod = (looper % NUMFUN);
			if (loopmod < 1)
				function5();
			if (loopmod < 2)
				function4();
			if (loopmod < 3)
				function3();
			if (loopmod < 4)
				function2();
			if (loopmod < 5)
				function1();
		}
	}

	// / Normal val1
	private void normalVal1() {
		for (long looper = 0; looper < outerloop; ++looper) {
			loopmod = (looper % NUMFUN);
			if (loopmod < 5)
				function1();
			if (loopmod < 4)
				function2();
			if (loopmod < 3)
				function3();
			if (loopmod < 2)
				function4();
			if (loopmod < 1)
				function5();
		}
	}

	// Functions to call
	private void function1() {
		for (long looper = 0; looper < innerloop; ++looper) {
			adder += Math.PI * 3;
			accumulator = (long) ((accumulator * 3) + adder);
		}
	}

	private void function2() {
		for (long looper = 0; looper < innerloop; ++looper) {
			adder += Math.PI * 3;
			accumulator = (long) ((accumulator * 3) + adder);
		}
	}

	private void function3() {
		for (long looper = 0; looper < innerloop; ++looper) {
			adder += Math.PI * 3;
			accumulator = (long) ((accumulator * 3) + adder);
		}
	}

	private void function4() {
		for (long looper = 0; looper < innerloop; ++looper) {
			adder += Math.PI * 3;
			accumulator = (long) ((accumulator * 3) + adder);
		}
	}

	private void function5() {
		for (long looper = 0; looper < innerloop; ++looper) {
			adder += Math.PI * 3;
			accumulator = (long) ((accumulator * 3) + adder);
		}
	}
}
