/**
  *
  * Programmieraufgabe P-18 (LogApproximatorTest.java)
  *
  * @author Leonhard Fellermayr
  * @version 1.0
  *
  */

/** Benoetigte Packages: Random und JUnit */

import java.util.Random;
import junit.framework.*;

/** Implementierung der Klasse LogApproximatorTest (erbt von TestCase) */

public class LogApproximatorTest extends TestCase
{

    /** ***** INSTANZVARIABLEN ***** */

    /** @param CASES Anzahl durchzufuehrender Versuche insgesamt (inklusive predefined) 
      * @param PREDEFINED_VALS Vordefinierte Versuchswerte
      * @param EPSILON Fehlerschranke
      * @param RANDOM_SEED Startwert fuer den Zufallszahlengenerator
      *
      * @param gen Instanz des Zufallszahlengenerators
      * @param xVals In diesem Array (Typ double[]) werden alle Versuchswerte gespeichert
      * @param xLogs In diesem Array (Typ LogApproximator[]) werden alle Versuchsergebnisse (Logarithmen) abgelegt
      */

    private final int      CASES           = 20;
    private final double[] PREDEFINED_VALS = { 0.10, 0.02, 1.2605e24 };
    private final double   EPSILON         = 0.000001;
    private final long     RANDOM_SEED     = 221281;

    private static Random     gen;
    private double[]          xVals;
    private LogApproximator[] xLogs;

    /** ***** UEBERSCHRIEBENE METHODEN ***** */

    /** setUp () : overwritten from TestCase */

    public void setUp ()
    {

	/** Initialisiere Zufallszahlengenerator mit vordefiniertem Startwert */

	gen   = new Random (RANDOM_SEED);

	/** Erzeuge Arrays mit der erforderlichen Groesse */

	xVals = new double[CASES];
	xLogs = new LogApproximator[CASES];

	/** Kopiere vordefinierte Versuchswerte aus dem final-Array in das "working" Array xVals[] */

	System.arraycopy (PREDEFINED_VALS, 0, xVals, 0, PREDEFINED_VALS.length);

	/** Erzeuge CASES - PREDEFINED_VALS.length zufaellige Versuchswerte und lege diese in xVals[] ab */

	for (int k = PREDEFINED_VALS.length; k < CASES; k++)

		/** Stellt sicher, dass 0.0 nicht unter den Versuchswerten ist */
		do
			xVals[k] = gen.nextDouble () * 2;
		while (xVals[k] == 0);

	/* Approximiere den natuerlichen Logarithmus fuer jeden Versuchswert mittels LogApproximator */

	for (int i = 0; i < CASES; i++)

		xLogs[i] = new LogApproximator (xVals[i]);

    } // setUp ()

    /** tearDown () : overwritten from TestCase */

    public void tearDown ()
    {
	/** @param cases_predefined Anzahl vordefinierter Versuchswerte
	  * @param cases_random Anzahl zufaellig generierter Versuchswerte */

	int cases_predefined = PREDEFINED_VALS.length;
	int cases_random     = CASES - cases_predefined;

	/** Kleine Konsolenausgabe */

	System.out.println (this.getName () + "() has to inspect " + CASES + " cases (" + cases_predefined + " predefined, " + cases_random + " random)");
    } // tearDown ()

    /** ***** TESTMETHODEN ***** */

    /** testArgumentFaktor () : Testet, ob sich bei der Berechnung von
      *
      * getArgument () * exp (getFaktor())
      *
      * wieder der urspruengliche Versuchswert ergibt (bei Toleranz EPSILON). */

    public void testArgumentFaktor ()
    {
	for (int i = 0; i < xVals.length; i++)
		Assert.assertEquals ("Fall #" + i + " : ln(" + xVals[i] + ")",
			              xVals[i],
                                      xLogs[i].getArgument () * Math.exp (xLogs[i].getFaktor()),
                                      EPSILON);
    } // testArgumentFaktor ()

    /** testNochUngenau () : Testet, ob nochUngenau () am Ende wirklcih true zurueckgibt. */

    public void testNochUngenau ()
    {
	for (int i = 0; i < xVals.length; i++)
		Assert.assertEquals ("Fall #" + i + " : ln(" + xVals[i] + ")",
			              true,			              xLogs[i].nochUngenau ());
    } // testNochUngenau ()

    /** testReExponentiateTheLog () : Exponentialisiert den berechneten Wert. PASS-Kriterium ist,
      * dass sich wieder der urspruengliche Versuchswert ergibt (bei Toleranz EPSILON). */

    public void testReExponentiateTheLog ()
    {
	for (int i = 0; i < xVals.length; i++)
		Assert.assertEquals ("Fall #" + i + " : ln(" + xVals[i] + ")",
			              xVals[i],			              Math.exp (xLogs[i].getLog ()),
				      EPSILON);
    } // testReExponentiateTheLog ()

    /** testValueEqualsOrigFunc () : Testet, ob Javas Math.log () den selben Logarithmus errechnet
      * wie unser Approximationsverfahren. */

    public void testValueEqualsOrigFunc ()
    {
	for (int i = 0; i < xVals.length; i++)
		Assert.assertEquals ("Fall #" + i + " : ln(" + xVals[i] + ")",
			              Math.log (xVals[i]),			              xLogs[i].getLog (),
				      EPSILON);
    } // testValueEqualsOrigFunc ()

    /** main () : Main-Methode der Klasse LogApproximatorTest : Ruft den TestRunner mit der Klasse
      * LogApproximatorTest als Argument auf (reflection). */

    public static void main (String[] args)
    {
	junit.textui.TestRunner.run (LogApproximatorTest.class);
    } // main ()

} // LogApproximatorTest ()
