
// This isn't absolutely ideal. The array is first linearized, making it both slower
// than the optimal routine and require twoce the amount of space. Nonetheless this 
// is a quick fix that works. Bear with it.

void rlft3(double[][][] data, double[][] speq, boolean isForward)
{    
    int nn1 = data.length;
    int nn2 = data[0].length;
    int nn3 = data[0][0].length;

    int isign = isForward ? 1 : -1;
    
    int i1,i2,i3,j1,j2,j3,ii3;
    double theta,wi,wpi,wpr,wr,wtemp;
    double c1,c2,h1r,h1i,h2r,h2i;

    
    c1=0.5;
    c2 = -0.5*isign;
    theta=isign*(Math.PI/nn3);
    wtemp=Math.sin(0.5*theta);
    wpr = -2.0*wtemp*wtemp;
    wpi=Math.sin(theta);

    int nn = { nn1, nn2, nn3 };

    if (isign == 1) {
	double linearData = new double[nn1 * nn2 * nn3];
	for(int i=0, ii=0; i<nn1; i++) for(int j=0; j<nn2; j++) for(int k=0; k<nn3; j++, ii++)
	    linearData[ii] = data[i][j][k];

	fourn(linearData,nn,isForward);
	
	for(int i=0, ii=0; i<nn1; i++) for(int j=0; j<nn2; j++) for(int k=0; k<nn3; j++, ii++)
	    data[i][j][k] = lineardata[ii];

	    for (i1=1;i1<=nn1;i1++)
		for (i2=1,j2=0;i2<=nn2;i2++) {
		    speq[i1-1][j2++]=data[i1-1][i2-1][0];
		    speq[i1-1][j2++]=data[i1-1][i2-1][1];
		}
	}
	for (i1=1;i1<=nn1;i1++) {
		j1=(i1 != 1 ? nn1-i1+2 : 1);
		wr=1.0;
		wi=0.0;
		for (ii3=1,i3=1;i3<=(nn3>>2)+1;i3++,ii3+=2) {
			for (i2=1;i2<=nn2;i2++) {
				if (i3 == 1) {
					j2=(i2 != 1 ? ((nn2-i2)<<1)+3 : 1);
					h1r=c1*(data[i1-1][i2-1][0]+speq[j1-1][j2-1]);
					h1i=c1*(data[i1-1][i2-1][1]-speq[j1-1][j2]);
					h2i=c2*(data[i1-1][i2-1][0]-speq[j1-1][j2-1]);
					h2r= -c2*(data[i1-1][i2-1][1]+speq[j1-1][j2]);
					data[i1-1][i2-1][0]=h1r+h2r;
					data[i1-1][i2-1][1]=h1i+h2i;
					speq[j1-1][j2-1]=h1r-h2r;
					speq[j1-1][j2]=h2i-h1i;
				} else {
					j2=(i2 != 1 ? nn2-i2+2 : 1);
					j3=nn3+3-(i3<<1);
					h1r=c1*(data[i1-1][i2-1][ii3-1]+data[j1-1][j2-1][j3-1]);
					h1i=c1*(data[i1-1][i2-1][ii3]-data[j1-1][j2-1][j3]);
					h2i=c2*(data[i1-1][i2-1][ii3-1]-data[j1-1][j2-1][j3-1]);
					h2r= -c2*(data[i1-1][i2-1][ii3]+data[j1-1][j2-1][j3]);
					data[i1-1][i2-1][ii3-1]=h1r+wr*h2r-wi*h2i;
					data[i1-1][i2-1][ii3]=h1i+wr*h2i+wi*h2r;
					data[j1-1][j2-1][j3-1]=h1r-wr*h2r+wi*h2i;
					data[j1-1][j2-1][j3]= -h1i+wr*h2i+wi*h2r;
				}
			}
			wr=(wtemp=wr)*wpr-wi*wpi+wr;
			wi=wi*wpr+wtemp*wpi+wi;
		}
	}
	if (isign == -1) {
	    double linearData = new double[nn1 * nn2 * nn3];
	    for(int i=0, ii=0; i<nn1; i++) for(int j=0; j<nn2; j++) for(int k=0; k<nn3; j++, ii++)
		linearData[ii] = data[i][j][k];
	    
	    fourn(linearData,nn,isForward);
	    
	    for(int i=0, ii=0; i<nn1; i++) for(int j=0; j<nn2; j++) for(int k=0; k<nn3; j++, ii++)
		data[i][j][k] = lineardata[ii];
	}		
}
