package gov.nist.androidsuite;

import android.os.Debug;
import android.os.Environment;

public class Val6 {
	/**
	 * val6.java 2013-06-04 4:27PM Reference executable for validating
	 * application profiling tools. val6: recursive function with workload at
	 * bottom of deep call stack.
	 * 
	 * Execute a workload after recursing beyond a specified depth. The exact
	 * maximum depth will depend on the initial depth of main and the number of
	 * levels of interrupt handler functions appearing below cycfn.
	 * 
	 * With default values of the parameters, the expected distribution of time
	 * is approximately main total 100 % self 0 % cycfn total 100 % self 100 %
	 * 
	 * For determining the depth at which trouble first appears, EACHLOOP may be
	 * set to generate an observable delay on each invocation. By default, no
	 * such delay is generated.
	 * 
	 * Test case suggested by José Fonseca, 2013-04-09.
	 * 
	 * Old (2013-04-29 14:20) Spin was for Windows + Intel Composer XE 2013 +
	 * Microsoft Visual Studio 2012. Language c99.
	 * 
	 * New Spin for Android + DDMS + Eclipse. Language Java.
	 */

	// Configurable LEAFLOOP: how many iterations in leaf invocation.
	private long leafloop = 1000000;

	// Configurable EACHLOOP: how many iterations in non-leaf invocations.
	private long eachloop = 0;

	// Configurable DEPTH: depth of recursion. MAX is 132 for Android Droidx
	// phone
	private long depth = 132;

	public String Output = "";

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

	// / Method to start calling of functions
	public int Start(int repeat, long LEAFLOOP, long EACHLOOP, long DEPTH,
			int TraceBuffer) {
		if (LEAFLOOP > 0) {
			leafloop = LEAFLOOP;
		}
		if (EACHLOOP >= 0) {
			eachloop = EACHLOOP;
		}
		if (DEPTH > 0 && DEPTH <= MainActivity.Val6DEPTH) {
			depth = DEPTH;
		}
		Debug.startMethodTracing(Environment.getExternalStorageDirectory()+"/Traces/ValSix" + Integer.toString(repeat),
				TraceBuffer);
		cycfn(depth);
		Debug.stopMethodTracing();
		Output = "Accumulator: " + accumulator + "\n" + "Adder: " + adder;
		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, leafloop, eachloop, depth, MainActivity.BufferToTrace);
	}

	private void cycfn(long DEPTH) {
		if (DEPTH > 0) {
			for (long looper = 0; looper < eachloop; ++looper) {
				adder += Math.PI * 3;
				accumulator = (long) ((accumulator * 3) + adder);
			}
			cycfn(DEPTH - 1);
		} else {
			for (long looper = 0; looper < leafloop; ++looper) {
				adder += Math.PI * 3;
				accumulator = (long) ((accumulator * 3) + adder);
			}
		}
	}
}
