Hi,

I wrote two functions, FWT2_PO and IWT2_PO, both having a 'transform' method. The functions work really well, but a strange thing happens.
Namely, the following code gives different output than the code below.

denoised = FWT2_PO.transform(array, 4, QMF, 2);
         //recovered=IWT2_PO.transform(denoised, 4, QMF);

        for (int i=0;i<denoised.length;i++){
            for (int j=0;j<denoised.length;j++){
                System.out.print(" ");
                System.out.print(denoised[i][j]);
                System.out.print("\t");
            }
            System.out.print("\n");
        }

The only difference is the one uncommented line

denoised = FWT2_PO.transform(array, 4, QMF, 2);
         recovered=IWT2_PO.transform(denoised, 4, QMF);

        for (int i=0;i<denoised.length;i++){
            for (int j=0;j<denoised.length;j++){
                System.out.print(" ");
                System.out.print(denoised[i][j]);
                System.out.print("\t");
            }
            System.out.print("\n");
        }

How can this happen?

Since you have not posted the code of the two functions I can only guess that the transform function mentioned in the commented line here :-

recovered=IWT2_PO.transform(denoised, 4, QMF);

is performing some modification(although it appears that it should not do so) in the value of the denoised array, (whose contents you are printing). Theres nothing strange in that, its normal.
Also reframe your way of asking questions, by the title of the thread strange java behaviour? , and also the way you posted, it appears as though you have claimed to have found a bug in the JDK, but it is the very basic concept of passing variables to functions (pass by value and pass by reference) which is at work here.

The IWT2_PO.transform method does not change anything to the first input argument. The first input argument to this function is immediately copied to a new variable. Also, shouldn't the input variable have a different scope anyway?

The IWT2_PO.transform method does not change anything to the first input argument. The first input argument to this function is immediately copied to a new variable. Also, shouldn't the input variable have a different scope anyway?

If it is an object it is passed by reference.
And when you say copy there are many ways to do it, and the behavior depends on the way you "copy".

Also you should post the code of the functions

Ok, here is the code:
As you can probably see, i'm not really a Java programmer. I'm used to Matlab, but my matlab code should be ported to java ... which i'm attempting now ;).

IWT2_PO:

package javaapplication4;

/**
 *
 * @author wiger van houten
 *
 * IWT2_PO -- Inverse 2-d MRA wavelet transform (periodized, orthogonal)
 *
 */
public class IWT2_PO {

    /**
     * @param args the command line arguments
     */
    public static double[][] transform(double[][] wc, int L, double[] QMF){

        int rows=wc.length;
        int cols=wc[1].length;
        int a = (int)Math.floor(Math.log(rows)/Math.log(2));
        int b = (int)Math.floor(Math.log(cols)/Math.log(2));
        int c = Math.min(a, b);

        int n=wc.length;
        int J=c;

        double[][] x=wc;
        int nc=(int)Math.pow(2,(L+1));
//        System.out.print("\n");
//        System.out.println(nc);

        for (int jscal=L;jscal<=J-1;jscal++){

            for (int iy=0;iy<nc;iy++){
                double bot[] = new double[nc/2];
                double top[] = new double[nc/2];
                for (int i=0;i<nc/2;i++){
                    bot[i]=x[i][iy];
                }
                for (int i=nc/2;i<nc;i++){
                    top[i-nc/2]=x[i][iy];
                }

                double tmp[]=UpDyadLo.filter(bot, QMF);
                double tmp2[]= UpDyadHi.filter(top, QMF);
                double tmp3[]=new double[nc];

                for (int k=0;k<nc;k++){
                    tmp3[k]=tmp[k]+tmp2[k];
                }

                for (int h=0;h<nc;h++){
                    x[h][iy]=tmp3[h];
                }
            }

            for (int ix=0;ix<nc;ix++){
                double bot[] = new double[nc/2];
                double top[] = new double[nc/2];
                for (int i=0;i<nc/2;i++){
                    bot[i]=x[ix][i];
                }
                for (int i=nc/2;i<nc;i++){
                    top[i-nc/2]=x[ix][i];
                }

                double tmp[]=UpDyadLo.filter(bot, QMF);
                double tmp2[]=UpDyadHi.filter(top, QMF);
                double tmp3[]=new double[nc];

                for (int k=0;k<nc;k++){
                    tmp3[k]=tmp[k]+tmp2[k];
                }

                for (int h=0;h<nc;h++){
                    x[ix][h]=tmp3[h];
                }
            }
            nc = 2*nc;
        }
        return x;
    }
}

and FWT2_PO:

package javaapplication4;

/**
 *
 * @author wiger van houten
 *
 * FWT2_PO -- 2-d MRA wavelet transform (periodized, orthogonal)
 * 
 */
public class FWT2_PO {

    /**
     * @param args the command line arguments
     */
    public static double[][] transform(double[][] image, int L, double[] QMF, double WGN){

        int rows=image.length;
        int cols=image[1].length;
        int a = (int)Math.floor(Math.log(rows)/Math.log(2));
        int b = (int)Math.floor(Math.log(cols)/Math.log(2));
        int c = Math.min(a, b);

        int n=image.length;
        int J=c;
        //
        //int L=4; // coarse level,
        // double wc[][] = new double[d][d];
        double wc[][] = image;
        double[][] denoised = new double[wc.length][wc.length];
        double finalestimate[][]=new double[wc.length][wc.length];
        
        int nc = n;

        for (int jscal=J-1;jscal>=L;jscal--){
                for (int ix=0;ix<nc;ix++){
                // L25 - select row
                double row[] = new double[nc];
                for (int i=0;i<nc;i++){
                    row[i]=wc[ix][i];
                }
                // there may be a faster way?

                double tmp[] = new double[row.length/2];
                tmp=DownDyadLo.filter(row, QMF);
                for (int i=0;i<row.length/2;i++){
                    wc[ix][i]=tmp[i];
                }

                for (int i=0;i<row.length/2;i++){
                    tmp[i]=0.0;
                }

                tmp=DownDyadHi.filter(row,QMF);
                for (int i=row.length/2;i<row.length;i++){
                    wc[ix][i]=tmp[i-row.length/2];
                }
            }

            for (int iy=0;iy<nc;iy++){
                // select column
                double row[] = new double[nc];
                for (int i=0;i<nc;i++){
                    row[i]=wc[i][iy];
                }
                // No need to transpose in this way

                double tmp[] = new double[row.length/2];
                tmp=DownDyadLo.filter(row,QMF);
                for (int i=0;i<row.length/2;i++){
                    wc[i][iy]=tmp[i];
                }

                for (int i=0;i<row.length/2;i++){
                    tmp[i]=0.0;
                }

                tmp=DownDyadHi.filter(row,QMF);
                for (int i=row.length/2;i<row.length;i++){
                    wc[i][iy]=tmp[i-row.length/2];
                }
            }

                // DENOISING STARTS HERE
                // we now have the wavelet coefficients.
                // diagonal band:
                finalestimate = matrix.minmatrix(
                                matrix.max( matrix.minus(matrix.square(  denoise.imfilter(matrix.selectdiag(wc, nc/2, nc), ones.matrix(3))   ), WGN*WGN)    ,0),
                                matrix.max( matrix.minus(matrix.square(  denoise.imfilter(matrix.selectdiag(wc, nc/2, nc), ones.matrix(5))   ), WGN*WGN)    ,0),
                                matrix.max( matrix.minus(matrix.square(  denoise.imfilter(matrix.selectdiag(wc, nc/2, nc), ones.matrix(7))   ), WGN*WGN)    ,0),
                                matrix.max( matrix.minus(matrix.square(  denoise.imfilter(matrix.selectdiag(wc, nc/2, nc), ones.matrix(9))   ), WGN*WGN)    ,0)
                                );

                for (int i=nc/2;i<nc;i++){
                    for (int j=nc/2; j<nc; j++){
                        denoised[i][j]= finalestimate[i-nc/2][j-nc/2];
                    }
                }

                // vertical band
                                finalestimate = matrix.minmatrix(
                                matrix.max( matrix.minus(matrix.square(  denoise.imfilter(matrix.selectvert(wc, nc/2, nc, 0, nc/2), ones.matrix(3))   ), WGN*WGN)    ,0),
                                matrix.max( matrix.minus(matrix.square(  denoise.imfilter(matrix.selectvert(wc, nc/2, nc, 0, nc/2), ones.matrix(5))   ), WGN*WGN)    ,0),
                                matrix.max( matrix.minus(matrix.square(  denoise.imfilter(matrix.selectvert(wc, nc/2, nc, 0, nc/2), ones.matrix(7))   ), WGN*WGN)    ,0),
                                matrix.max( matrix.minus(matrix.square(  denoise.imfilter(matrix.selectvert(wc, nc/2, nc, 0, nc/2), ones.matrix(9))   ), WGN*WGN)    ,0)
                                );

                for (int i=nc/2;i<nc;i++){
                    for (int j=0; j<nc/2; j++){
                        denoised[i][j]= finalestimate[i-nc/2][j];
                    }
                }

                // horizontal band
                                                // horizontal band
                                finalestimate = matrix.minmatrix(
                                matrix.max( matrix.minus(matrix.square(  denoise.imfilter(matrix.selectvert(wc, 0, nc/2, nc/2, nc), ones.matrix(3))   ), WGN*WGN)    ,0),
                                matrix.max( matrix.minus(matrix.square(  denoise.imfilter(matrix.selectvert(wc, 0, nc/2, nc/2, nc), ones.matrix(5))   ), WGN*WGN)    ,0),
                                matrix.max( matrix.minus(matrix.square(  denoise.imfilter(matrix.selectvert(wc, 0, nc/2, nc/2, nc), ones.matrix(7))   ), WGN*WGN)    ,0),
                                matrix.max( matrix.minus(matrix.square(  denoise.imfilter(matrix.selectvert(wc, 0, nc/2, nc/2, nc), ones.matrix(9))   ), WGN*WGN)    ,0)
                                );

                for (int i=0;i<nc/2;i++){
                    for (int j=nc/2; j<nc; j++){
                        denoised[i][j]= finalestimate[i][j-nc/2];
                    }
                }
                // DENOISING STOPS HERE
            nc = nc/2;
        }

                // DENOISING CONTINUOUS HERE
        double[][] denoised2=new double[wc.length][wc.length];

        for (int i=0; i<wc.length;i++){
            for (int j=0;j<wc.length; j++){
                denoised2[i][j]=wc[i][j]*denoised[i][j]/(denoised[i][j]+WGN*WGN);
            }
        }

        for (int i=0; i<32;i++){
            for (int j=0; j<32; j++){
                denoised2[i][j]=wc[i][j];
            }
        }
                // DENOISING FINISHES HERE
        return denoised2;
    }
}

The IWT2_PO.transform method does not change anything to the first input argument. The first input argument to this function is immediately copied to a new variable. Also, shouldn't the input variable have a different scope anyway?

Incorrect, you are passing an Array, so it will be passed by reference and not passed by value, so any modifications done in that function to it would be reflected here.

Try out this piece of code, you will make out the concept:-

class ArrayTester {

  public static void modify(int a[]) {
    a[0]=99;
  }
  public static void main(String[] args) {
    int beta[] = new int[10];
    beta[0]=1;
    System.out.println("beta[0] = " + beta[0]);
    modify(beta);
    System.out.println("beta[0] = " + beta[0]);
  }
}

It will output :-

stephen@steve:~/Development/java/daniweb> java ArrayTester
beta[0] = 1
beta[0] = 99

<EDIT>

I guess JavaAddict beat to the next post.

In your first method you do this: double[][] x=wc; Meaning that changes you perform to one or the other array(object) will be applied to the other because they are the same.
But if you had something like this:

double[][] x = new double[wc.length][];

for (int i=0;i<x.length;i++) {

  x[i] = new double[wc[i].length];

  for (int j=0;j<x[i].length;j++) {
     x[i][j] = wc[i][j];
  }
}

Notice this: x[j] = wc[j]; instead of what you wrote: double[][] x=wc;

Here is your problem, line 28 of FWT2_PO

double[][] x=wc;

You cannot copy arrays like that in Java. "x" would still refer to the original array.
Use something like this to copy your array wc to x:-

int[] copy = (int[])aArray.clone();

<EDIT>
:P Again javaAddict beat me to it.

Thanks a lot! As I said, I'm not an experienced Java programmer; I did most of my programming in Matlab (where you can easily copy arrays like I did), and a little in C (where passing by reference is much clearer).

Again, thanks a lot! I think I understand it, and I'll figure it out now ;).

This question has already been answered. Start a new discussion instead.