package gov.nist.androidsuite;

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

public class Val3 {
	/**
	 * val3.java 2013-06-04 3:53PM Reference executable for validating
	 * application profiling tools. val3: mutually recursive functions.
	 * 
	 * With default values of FN1LOOP and FN2LOOP, the expected distribution of
	 * time is approximately main total 100 % self 0 % cycfn2 total 100 % self
	 * 67 % cycfn1 total 67 % self 33 % resulting from the following call chains
	 * and proportions of samples: 2 main->cycfn2 1 main->cycfn2->cycfn1 2
	 * main->cycfn2->cycfn1->cycfn2 1 main->cycfn2->cycfn1->cycfn2->cycfn1
	 * 
	 * 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.
	 */

	// Configurable FN1LOOP: how many busy-work iterations in cycfn1.
	private long fn1loop = 125000;

	// Configurable FN2LOOP: how many busy-work iterations in cycfn2.
	private long fn2loop = fn1loop * 2;

	public String Output = "";

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

	// / Method to start calling of functions
	public int Start(int repeat, long FN1LOOP, long FN2LOOP, int TraceBuffer) {
		if (FN1LOOP > 0) {
			fn1loop = FN1LOOP;
			fn2loop = fn1loop * 2;
		}
		if (FN2LOOP > 0) {
			fn2loop = FN2LOOP;
		}
		Debug.startMethodTracing(Environment.getExternalStorageDirectory()+"/Traces/ValThree" + Integer.toString(repeat),
				TraceBuffer);
		cycfn2(false);
		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, fn1loop, fn2loop, MainActivity.BufferToTrace);
	}

	private void cycfn2(boolean leaf) {
		for (long looper = 0; looper < fn2loop; ++looper) {
			adder += Math.PI * 3;
			accumulator = (long) ((accumulator * 3) + adder);
		}
		cycfn1(leaf);
	}

	private void cycfn1(boolean leaf) {
		for (long looper = 0; looper < fn1loop; ++looper) {
			adder += Math.PI * 3;
			accumulator = (long) ((accumulator * 3) + adder);
		}
		if (!leaf) {
			cycfn2(true);
		}
	}
}
