/**
 *  Benchmark #7 - Monte-Carlo Form-factor computation.
 *   @author  Josef.Pelikan@mff.cuni.cz
 *   @version 0.007 (2001/06/17)
 *   @since   0.007
 */
public class BenchmarkFormFactor extends Benchmark {

    /** Number of tries. */
    protected final static int FF_ITER = 50000000;

    /** Number of full hits. */
    protected int fullHits;

    /** Number of half rays. */
    protected int halfCount;

    /** Number of half hits. */
    protected int halfHits;

    /**
     *  Initializing constructor.
     */
    public BenchmarkFormFactor () {
        fullHits = halfCount = halfHits = 0;
    }

    /**
     *  Test (benchmark) ordinal number.
     *   @return Ordinal number of the test.
     */
    public int testNumber () {
        return 7;
    }

    /**
     *  The benchmark algorithm itself. Needs not be re-entrant but can be iterated.
     */
    protected void test () {
        fullHits = halfCount = halfHits = 0;
        double x0, y0;                      // ray origin
        double x1, y1, z1;                  // ray direction
        double x2, y2;
        double tmp;
        boolean half;
        int i;
        RandomJames rnd = new RandomJames();
        for ( i = 0; i++ < FF_ITER; ) {
            x0 = rnd.uniformNumber();
            y0 = rnd.uniformNumber();
            if ( (half = x0 < 0.5 && y0 < 0.5) ) halfCount++;
            do {
                x1 = rnd.uniformNumber() * 2.0 - 1.0;
                y1 = rnd.uniformNumber() * 2.0 - 1.0;
                tmp = x1 * x1 + y1 * y1;
                } while ( tmp >= 1.0 );
            z1 = Math.sqrt( 1.0 - tmp );
            if ( z1 > 0.01 ) {              // there is a chance
                tmp = 1.0 / z1;
                x2 = x0 + tmp * x1;
                y2 = y0 + tmp * y1;
                if ( x2 >= 0.0 && y2 >= 0.0 )
                    if ( x2 < 1.0 && y2 < 1.0 ) {
                        fullHits++;
                        if ( half && x2 < 0.5 && y2 < 0.5 ) halfHits++;
                        }
                }
            }
    }

    /**
     *  Result string of the test. Should be called after the <code>runTest()</code>
     *  was finished.
     *   @return Result of the test.
     */
    public String testResult () {
        return( "Form-factor: iter = " + (FF_ITER/1000000) +
                "M, Ffull = " + ((double)fullHits/FF_ITER) +
                ", Fhalf = " + ((double)halfHits/halfCount) );
    }

}
