/**
 *  Benchmark #2 to 3 - Image transposition.
 *   @author  Josef.Pelikan@mff.cuni.cz
 *   @version 0.007 (2001/06/17)
 *   @since   0.007
 */
public class BenchmarkTranspose extends Benchmark {

    /**
     *  Initializing constructor.
     *   @param  ord Ordinal number of the test (valid values: 2 to 3).
     *   @param  _alt Alternative flag.
     */
    public BenchmarkTranspose ( int ord, boolean _alt ) {
        if ( ord < 2 ) ord = 2;
        if ( ord > 3 ) ord = 3;
        order = ord;
        alt = _alt;
    }

    /** Ordinal number of the test. */
    protected int order;

    /** Image sizes (1 byte per pixel). */
    protected final static int size[] = { 4096, 8192 };

    /** Number of iterations. */
    protected final static int iter[] = { 48, 12 };

    /** Test alternative: use byte array access only. */
    protected boolean alt;

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

    /**
     *  Transposes the given image <code>src</code>, result will be written to <code>dest</code>.
     *   @param  dest Result image.
     *   @param  src Source image.
     */
    protected static void transpose ( byte[][] dest, byte[][] src ) {
        int height = dest.length;
        int width = dest[0].length;
        int i, j;
        for ( i = 0; i < height; i++ )
            for ( j = 0; j < width; j++ )
                dest[i][j] = src[j][i];
    }

    /**
     *  Transposes the given image <code>src</code>, result will be written to <code>dest</code>.
     *   @param  dest Result image.
     *   @param  src Source image.
     */
    protected static void transpose ( int[][] dest, int[][] src ) {
        int height = dest.length;
        int width = dest[0].length;
        int i, j, srcI, srcJ;
        for ( i = srcJ = 0; i < height;
              i += 4, srcJ++ ) {            // one image strip
            for ( j = srcI = 0; j < width;
                  j++, srcI += 4 ) {        // one 4x4 rectangle
                int s0 = src[srcI  ][srcJ];
                int s1 = src[srcI+1][srcJ];
                int s2 = src[srcI+2][srcJ];
                int s3 = src[srcI+3][srcJ];
                dest[i  ][j] =  (s0 & 0xFF)            + ((s1 & 0xFF)<<8) +
                               ((s2 & 0xFF)<<16)       + ((s3 & 0xFF)<<24);
                dest[i+1][j] =  ((s0>>8) & 0xFF)       + (((s1>>8) & 0xFF)<<8) +
                               (((s2>>8) & 0xFF)<<16)  + (((s3>>8) & 0xFF)<<24);
                dest[i+2][j] =  ((s0>>16) & 0xFF)      + (((s1>>16) & 0xFF)<<8) +
                               (((s2>>16) & 0xFF)<<16) + (((s3>>16) & 0xFF)<<24);
                dest[i+3][j] =  ((s0>>24) & 0xFF)      + (((s1>>24) & 0xFF)<<8) +
                               (((s2>>24) & 0xFF)<<16) + (((s3>>24) & 0xFF)<<24);
                }
            }
    }

    /**
     *  The benchmark algorithm itself. Needs not be re-entrant but can be iterated.
     */
    protected void test () {
        int i;
        if ( alt ) {                        // byte[][] image representation
            byte[][] im1 = new byte[size[order-2]][size[order-2]];
            byte[][] im2 = new byte[size[order-2]][size[order-2]];
            for ( i = 0; i++ < iter[order-2]; ) {
                transpose(im2,im1);
                transpose(im1,im2);
                }
            }
        else {                              // int[][] image representation
            int[][] im1 = new int[size[order-2]][size[order-2]>>2];
            int[][] im2 = new int[size[order-2]][size[order-2]>>2];
            for ( i = 0; i++ < iter[order-2]; ) {
                transpose(im2,im1);
                transpose(im1,im2);
                }
            }
    }

    /**
     *  Result string of the test. Should be called after the <code>runTest()</code>
     *  was finished.
     *   @return Result of the test.
     */
    public String testResult () {
        return( "Transpose the [" + size[order-2] + "," + size[order-2] + "] image" );
    }

}
