Skip to content
Snippets Groups Projects
cc2dfft.c 4.93 KiB
#include "genfft.h"
#ifdef MKL
#include "mkl_dfti.h"
void dfti_status_print(MKL_LONG status);
#endif

/**
*   NAME:     cc2dfft
*
*   DESCRIPTION: 2 Dimensional complex to complex FFT
*
*   USAGE:
*         void cc2dfft(complex *data, int nx, int ldx, 
*                      int ny, int sign)
*
*   INPUT:  - *data: complex 2D input array
*           -    nx: number of x (fast) samples to be transformed
*           -   ldx: leading dimension in fast direction
*           -    ny: number of y (slow) samples to be transformed
*           -  sign: sign of the Fourier kernel
*
*   OUTPUT: - *data: complex 2D output array unscaled
*
*   NOTES: Optimized system dependent FFT's implemented for:
*          - CRAY T3D and T3E
*          - CRAY T90
*          - CRAY J90
*          - SGI/CRAY ORIGIN 2000 (scsl)
*          - SGI Power Challenge (complib.sgimath)
*          - inplace FFT from Mayer and SU (see file fft_mayer.c)
*
*   AUTHOR:
*           Jan Thorbecke (janth@xs4all.nl)
*           The Netherlands
*
*----------------------------------------------------------------------
*  REVISION HISTORY:
*  VERSION        AUTHOR          DATE         COMMENT
*    1.0       Jan Thorbecke    July  '97    Initial version
*
----------------------------------------------------------------------*/

#if defined(ACML440)
	#if defined(DOUBLE) 
		#define acmlcc2dfft zfft2dx
	#else
		#define acmlcc2dfft cfft2dx
	#endif
#endif

void cc2dfft(complex *data, int nx, int ny, int ldx, int sign)
{
#if defined(HAVE_LIBSCS)
	int pe;
	static int nx_prev[MAX_NUMTHREADS], ny_prev[MAX_NUMTHREADS];
	int   isys=0, ntable, nwork, zero=0;
	static float *work[MAX_NUMTHREADS], *table[MAX_NUMTHREADS];
	float scale=1.0;
#elif defined(ACML440)
	static int nyprev=0, nxprev=0;
	int   nwork, zero=0, one=1, i, j, inpl, ltrans;
	static int isys;
	static complex *work;
	REAL scl;
	complex *y;
	complex *tmp;
#elif defined(MKL)
    static DFTI_DESCRIPTOR_HANDLE handle=0;
    static int nxprev=0, nyprev=0;
    MKL_LONG Status, N[2];
#else
	int i, j;
	complex *tmp;
#endif

#if defined(HAVE_LIBSCS)
	pe = mp_my_threadnum();
	if (ny != 1) {
		if (nx != nx_prev[pe] || ny != ny_prev[pe]) {
			nwork = 2*nx*ny;
			ntable = 60+2*(nx+ny);
			if (work[pe]) free (work[pe]);
			if (table[pe]) free (table[pe]);
			work[pe]  = (float *)malloc(nwork*sizeof(float));
			if (work[pe] == NULL) 
				fprintf(stderr,"cc2dfft: memory allocation error\n");
			table[pe] = (float *)malloc(ntable*sizeof(float));
			if (table[pe] == NULL) 
				fprintf(stderr,"cc2dfft: memory allocation error\n");
			ccfft2d_(&zero,&nx,&ny,&scale,data,&ldx,data,&ldx,
				table[pe],work[pe],&isys);
			nx_prev[pe] = nx;
			ny_prev[pe] = ny;
		}
		ccfft2d_(sign,&nx,&ny,&scale,data,&ldx,data,&ldx,
			table[pe],work[pe],&isys);
	}
	else {
		cc1fft(data, nx, sign);
	}
#elif defined(ACML440)
	scl = 1.0;
	inpl = 1;
	ltrans = 1;
	if (ny != 1) {
		if (nx != nxprev || ny != nyprev) {
			isys   = 0;
			nwork  = ny*nx+5*nx+5*ny+200;
			if (work) free(work);
			work = (complex *)malloc(nwork*sizeof(complex));
			if (work == NULL) fprintf(stderr,"cc2dfft: memory allocation error\n");
			acmlcc2dfft(zero, scl, ltrans, inpl, nx, ny, data, 1, ldx, y, 1, ldx, work, &isys);
			nxprev = nx;
			nyprev = ny;
		}
		acmlcc2dfft(sign, scl, ltrans, inpl, nx, ny, data, 1, ldx, y, 1, ldx, work, &isys);
	}
	else {
		cc1fft(data, nx, sign);
	}
#elif defined(MKL)
	if (nx != nxprev || ny != nyprev) {
        DftiFreeDescriptor(&handle);
          
		N[0] = nx; N[1] = ny;
        Status = DftiCreateDescriptor(&handle, DFTI_SINGLE, DFTI_COMPLEX, 2, N);
        if(! DftiErrorClass(Status, DFTI_NO_ERROR)){
            dfti_status_print(Status);
            printf(" DftiCreateDescriptor FAIL\n");
        } 
        Status = DftiCommitDescriptor(handle);
        if(! DftiErrorClass(Status, DFTI_NO_ERROR)){
            dfti_status_print(Status);
            printf(" DftiCommitDescriptor FAIL\n");
        }
        nxprev = nx;
        nyprev = ny;
    }
    if (sign < 0) {
    	Status = DftiComputeBackward(handle, data);
    }
    else {
    	Status = DftiComputeForward(handle, data);
    }   
#else 
	if (ny != 1) {
		ccmfft(data, nx, ny, ldx, sign);
		tmp = (complex *)malloc(nx*ny*sizeof(complex));
		if (tmp == NULL) fprintf(stderr,"cc2dfft: memory allocation error\n");
		for (i=0; i<nx; i++) {
			for (j=0; j<ny; j++) tmp[j+i*ny] = data[j*ldx+i];
		}
		ccmfft(tmp, ny, nx, ny, sign);
		for (i=0; i<nx; i++) {
			for (j=0; j<ny; j++) data[j*ldx+i] = tmp[j+i*ny];
		}
/*
		for (i=0; i<nx; i++) {
			for (j=0; j<ny; j++) tmp[j] = data[j*ldx+i];
			cc1fft(tmp, ny, sign);
			for (j=0; j<ny; j++) data[j*ldx+i] = tmp[j];
		}
*/
		free (tmp);
	}
	else {
		cc1fft(data, nx, sign);
	}
#endif

	return;
}

void free_cc2dfft()
{
	return;
}

/****************** FORTRAN SHELL *****************/

#ifdef DF_CAPFNAMES
#define ncc2dfft FNAME(CC2DFFTF)
#else
#define ncc2dfft FNAME(cc2dfftf)
#endif

void ncc2dfft(complex *data, int *nx, int *ny, int *ldx, int *sign)
{
	cc2dfft(data, *nx, *ny, *ldx, *sign);

	return;
}