/* fft.c Copyright (c) Kapteyn Laboratorium Groningen 1992 All Rights Reserved. This program does a two-dimensional in place Fourier transform on a pair of maps. The data for the inplace transform are stored in a scratch file. Special routines have been written to access this file by row number. A row consists of a data string of two times the length of a map row, the first half containing the real part of the data, the second half the imaginary part. The FFT subroutine FFTX is partly based on the subroutine FOUR1 by Norman Brenner (MIT, 1971), and adapted for the GIPSY data structure by K. Begeman. The subroutine FFTY is also based on FOUR1. Since in the GIPSY data-base the real and imaginary parts are stored in different parts of the file (set), the standard FORTRAN definition of complex data is not handy, because then we need to do lots of - complicated - time consuming transpose operations on the data. In order to avoid this, we defined a complex array as follows: complex CBUF(N) standard FORTRAN: real1,imag1,real2,imag2,...........,realN,imagN here: real1,real2,.....,realN,imag1,imag2,.....,imagN NOTES: To change the maximum map size this program can handle, simply change all parameter statements for MAXP2. routines: BITREV calculates the bit-reversed integer. CLOSEF closes and removes scratch file. FFTX does the transform in X direction. FFTY does the transform in Y direction. FXCX fixes up complex rows for FFTY. FXRL fixes up real <--> complex transform. GETROW reads a row from scratch file. INPMAP loads data into scratch file and does the FFT in x (if FORM=-1 or 1). MIRROR reverse order conjugates the FFT image. OPENF creates scratch file. OUTMAP gets result of FFT from scratch file, and does the FFT in x (if FORM=0). PUTROW writes a row to scratch file. READXY reads from GIPSY subset. SHIFTR function which converts FFT coordinates into map coordinates. SHIFTX function which converts FFT coordinates with respect to a centre offset. VECTOR routine which does the conversion from amplitude and phase to cosine and sine, or the other way around. WRITXY writes to GIPSY subset. other routines referenced are standard GIPSY routines #> fft.dc1 Program: FFT Purpose: This program does a two-dimensional Fast Fourier Transform on a (pair of) map(s). Maximum map size is 2048 x 2048. Category: MANIPULATION File: fft.c Author: K.G. Begeman Keywords: RINSET= set and subset(s) input map(s) which contain the real part or the amplitude. Maximum number of maps is 2048. IINSET= set and subsets(s) input map(s) which contain the imaginairy part or phase [no imaginairy part]. ROUTSET= set and subset(s) output map(s) which will contain the real part or amplitude. IOUTSET= set and subset(s) output map(s) which will contain the imaginairy part or phase [no imaginairy part]. ** SIGN= sign of transform (1 or -1). If it is not clear from the number of input and output sets, this keyword will appear. Example: 1 input set, 1 output set ---> SIGN=+1 (for AP's) 1 input set, 2 output sets ---> SIGN=-1 2 input sets, 1 output set ---> SIGN=+1 2 input sets, 2 output sets ---> will be asked SIGN=-1 sky to visibility SIGN=+1 visibility to sky ** PHASE= input/output maps in amplitude and phase [Y]? Note that if only one input/output set is wanted, it is assumed by this program that the input/output set is COS and the SIN part is zero. ** VALUE= Replace BLANKs in input sets by value [0.0]. Notes: 1) This program can only handle maps where the number of pixels in X and Y are a power of two! The minimum map size this program can handle is 16x16. 2) This program is optimized for real to complex or complex to real transforms. 3) The program tries to allocate as much memory as needed. If the allocation fails, it will create a scratch file. Updates: Aug 23, 1992: KGB, Document created. #< */ /* * includes: */ #include "math.h" /* */ #include "stddef.h" /* */ #include "stdio.h" /* */ #include "stdlib.h" /* */ #include "string.h" /* */ #include "gipsyc.h" /* GIPSY definitions */ #include "cmain.h" /* programme in C */ #include "anyout.h" /* anyout_c */ #include "error.h" /* error_c */ #include "fextend.h" /* fextend_c */ #include "finis.h" /* finis_c */ #include "gdsasn.h" /* gdsasn_c */ #include "gdsc_fill.h" /* gdsc_fill_c */ #include "gdsc_grid.h" /* gdsc_grid_c */ #include "gdsc_ndims.h" /* gdsc_ndims_c */ #include "gdsc_range.h" /* gdsc_range_c */ #include "gdsi_read.h" /* gdsi_read_c */ #include "gdsi_write.h" /* gdsi_write_c */ #include "gdsinp.h" /* gdsinp_c */ #include "gdsout.h" /* gdsout_c */ #include "init.h" /* init_c */ #include "minmax3.h" /* minmax3_c */ #include "nelc.h" /* nelc_c */ #include "setfblank.h" /* setfblank_c */ #include "status.h" /* status_c */ #include "userint.h" /* userint_c */ #include "userlog.h" /* userlog_c */ #include "userreal.h" /* userreal_c */ #include "wminmax.h" /* wminmax_c */ /* * Defines: */ #define ABS(x) (x<0?-x:x) /* absolute value */ #define CLASSDIM 2 /* wanted subset dim */ #define MAXAXES 10 /* max. number of axis */ #define MAX(x,y) (x>y?x:y) /* maximum */ #define MIN(x,y) (x= ipix ) k2 = 0; tr = cbuf[k1]; ti = cbuf[k1+ipix]; cbuf[k1] = cbuf[k2]; cbuf[k1+ipix] = -cbuf[k2+ipix]; cbuf[k2] = tr; cbuf[k2+ipix] = -ti; } } /* * shiftr calculates a line number in the map corresponding with the FFT * row number. */ static fint shiftr( fint ioff , /* bottom line number */ fint ipix , /* number of pixels (flip over border) */ fint irow ) /* FFT row number */ { fint idum; idum = ipix + ioff - 1; /* idum is map largest line number */ if ( irow > idum ) { return( irow - ipix ); } else { return( irow ); } } /* * shiftx calculates the position in an array corresponding with the FFT * address. */ static fint shiftx( fint ioff , /* offset from centre */ fint ipix , /* number of pixels (flip over border) */ fint ifft ) /* FFT address */ { fint idum; idum = ifft + ioff; /* idum is shifted FFT address */ if ( idum < ipix ) { return( idum ); } else { return( idum - ipix ); } } /* * vector converts cos. and sin. into amp. and pha., or the other way around. */ static void vector( float cbuf[] , /* complex array */ fint n , /* number of elements cbuf */ fint m1 , /* input type of data */ fint m2 ) /* output type of data */ { fint k; float a, b; if ( m1 == m2 ) return; /* quick solution possible ? */ if ( m2 == 1 ) { /* from amp. and pha. to cos. and. sin. */ for ( k = 0; k < n; k++ ) { a = cbuf[k]; b = cbuf[k+n] / RAD; cbuf[k] = a * cos( b ); cbuf[k+n] = a * sin( b ); } } else { /* from cos. and. sin. to amp. and pha. */ for ( k = 0; k < n; k++ ) { a = cbuf[k]; b = cbuf[k+n]; cbuf[k] = sqrt( a * a + b * b ); if ( cbuf[k] == 0.0 ) { /* zero amplitude ? */ cbuf[k+n] = 0.0; } else { cbuf[k+n] = RAD * atan2( b , a ); } } } } /* * fftx does a one dimensional in place FT. */ static void fftx( float cbuf[] ) /* array with complex data */ { fint i, ii, l; for ( ii = 0; ii < NPTX; ii++ ) { fint ir = REVTAB[ii]; /* * to prevent re-exchanging, i must not be greater than than ir */ if ( ir >= ii ) { fint jj, jr, jjn, jrn; float tr, ti; jj = XOFTAB[ii]; jr = XOFTAB[ir]; jjn = jj + NPTX; jrn = jr + NPTX; tr = cbuf[jj]; ti = cbuf[jjn]; cbuf[jj] = FACTAB * cbuf[jr]; cbuf[jjn] = FACTAB * cbuf[jrn]; cbuf[jr] = FACTAB * tr; cbuf[jrn] = FACTAB * ti; } } /* * separate the data into even and odd subsequences, * transform each, phase shift the odd transform and * add them. this recursive formulation of the FFT is * here written iteratively from the innermost subtransform * outward. */ for ( l = 0; l < LOGP2X; l++ ) { fint i2l, istep, q; i2l = POWTAB[l]; istep = 2 * i2l; q = POWTAB[ MAXP2 - l - 1 ]; for ( i = 0; i < i2l; i++ ) { fint ia, itab; float wr, wi; itab = i * q; /* get index of table entry */ wr = COSTAB[itab]; /* get cosine from table */ wi = SINTAB[itab] * SIGN; /* get sine from table */ for ( ia = i; ia < NPTX; ia += istep ) { fint ib, ja, jb, jan, jbn; float tr, ti, ur, ui, vr, vi; ib = ia + i2l; ja = XOFTAB[ia]; jb = XOFTAB[ib]; jan = ja + NPTX; jbn = jb + NPTX; ur = cbuf[jb]; ui = cbuf[jbn]; vr = cbuf[ja]; vi = cbuf[jan]; tr = wr * ur - wi * ui; ti = wr * ui + wi * ur; cbuf[ja] = vr + tr; cbuf[jan] = vi + ti; cbuf[jb] = vr - tr; cbuf[jbn] = vi - ti; } } } } /* * fxcx combines two complex arrays for subroutine ffty. */ static void fxcx( float wr , /* cosine term */ float wi , /* sine term */ float row1[] , /* first row (complex array) */ float row2[] , /* second row (complex array) */ fint n ) /* number of points */ { fint lx, ly; float i1, i2, r1, r2, tr, ti; for ( lx = 0; lx < n; lx++ ) { ly = lx + n; r1 = row1[lx]; i1 = row1[ly]; r2 = row2[lx]; i2 = row2[ly]; tr = wr * r2 - wi * i2; ti = wr * i2 + wi * r2; row1[lx] = r1 + tr; row1[ly] = i1 + ti; row2[lx] = r1 - tr; row2[ly] = i1 - ti; } } /* * ffty does a one dimensional in place Fourier tansform in the Y direction. * The bit-reversal is done by inpmap. */ static void ffty( void ) { fint l, lp2; float row1[2*SIZE], row2[2*SIZE]; lp2 = 2 * NPTX; /* number of points in row */ /* * separate the data into even and odd subsequences, * transform each, phase shift the odd transform and * add them. this recursive formulation of the FFT is * here written iteratively, from the innermost * subtransform outward. */ for ( l = 0; l < LOGP2Y; l++ ) { fint i, i2l, istep, q; i2l = POWTAB[l]; istep = 2 * i2l; q = POWTAB[ MAXP2 - l - 1 ]; for ( i = 0; i < i2l; i++ ) { fint ia, ib, itab; float wr, wi; itab = i * q; /* get table entry */ wr = COSTAB[itab]; /* get cosine from table */ wi = SINTAB[itab] * SIGN; /* get sine from table */ for ( ia = i; ia < NPTY; ia += istep ) { ib = ia + i2l; getrow( row1, lp2, ia ); getrow( row2, lp2, ib ); fxcx( wr, wi, row1, row2, NPTX ); putrow( row1, lp2, ia ); putrow( row2, lp2, ib ); } } } } /* * fxrl fixes up a real or half-size complex array for 2 complex arrays (=rows). */ static void fxrl( float zr , /* real factor */ float zi , /* imaginary factor */ float row1[] , /* complex array (data from row r1) */ float row2[] , /* complex array (data from row r2) */ fint r1 , /* first row number */ fint r2 , /* second row number */ fint n ) /* number of complex numbers in rows */ { fint i, j; /* counters */ float di, dr, ti, tr; for ( i = 0; i < n; i++ ) { j = i + n; dr = row1[i] - row2[i]; di = row1[j] + row2[j]; tr = zr * dr - zi * di; ti = zr * di + zi * dr; row1[i] = row1[i] - tr; row1[j] = row1[j] - ti; if ( r1 < r2 ) { row2[i] = row2[i] + tr; row2[j] = row2[j] - ti; } } } /* * inpmap loads the data into the scratch file, and does the FFT in x * if IFORM=-1 or 1. */ static void inpmap( fint lpt , /* number of points in X */ fint mpt , /* number of points in Y */ fint lmin , /* left most x map coordinate */ fint mmin , /* lower most y map coordinate */ fchar set[] , /* input set name */ fint sub[] , /* subsets */ fint nset , /* number of sets */ fint modi ) /* input mode, amp./pha. or cos./sin. */ { fint i, itab, k, m, md, mi, mj, mph, mphh, ms; fint q, r, ri, rj, row, rs, wor; float rbuf[2*SIZE], cbuf[2*SIZE]; float fr, fi, zr, zi; if ( FORM == -1 ) { /* complex ---FFT---> real */ q = POWTAB[ MAXP2 - LOGP2Y - 1 ]; /* table offset factor */ mph = mpt / 2; /* number of rows to load */ mphh = mph / 2 + 1; fr = -0.5 * SIGN; /* calculate factors */ fi = -0.5; for ( ri = 0 ; ri < mphh; ri++ ) { /* loop to load data */ rj = mph - ri; itab = ri * q; /* get table position */ zr = 0.5 - fr * SINTAB[itab]; zi = fi * COSTAB[itab]; mi = shiftr( mmin, mpt, ri ); for ( k = 0; k < nset; k++ ) { /* get data */ i= k * lpt; readxy( set[k], sub[k], lmin, mi, &cbuf[i], lpt, 1 ); } mj = shiftr( mmin, mpt, rj ); for ( k = 0; k < nset; k++ ) { /* get data */ i = k * lpt; readxy( set[k], sub[k], lmin, mj, &rbuf[i], lpt, 1 ); } vector( cbuf, lpt, modi, 1 ); vector( rbuf, lpt, modi, 1 ); fftx( cbuf ); /* do the FFT */ fftx( rbuf ); /* fixup for complex to real transform */ fxrl( zr, zi, cbuf, rbuf, ri, rj, lpt ); /* store in scratch file */ wor = bitrev( ri, LOGP2Y ); putrow( cbuf, 2 * lpt, wor ); if ( ( ri != rj ) && ( ri != 0 ) ) { wor = bitrev( rj, LOGP2Y ); putrow( rbuf, 2 * lpt, wor ); } } } else if ( FORM == 0 ) { /* real ---FFT---> complex */ rs = MIN( mpt, ( 2 * SIZE ) / lpt ); /* number of rows in one pass */ k = 0; /* subset number */ for ( r = 0; r < mpt; r += rs ) {/* loop to load data */ md = 0; do { m = shiftr( mmin, mpt, r + md ); ms = MIN( rs - md, mpt + mmin - m ); i = md * lpt; readxy( set[k], sub[k], lmin, m, &cbuf[i], lpt, ms ); md = md + ms; } while ( md != rs ); for ( row = r; row < ( r + rs ); row += 2 ) { i = ( row - r ) * lpt; wor = bitrev( row / 2, LOGP2Y ); putrow( &cbuf[i], 2 * lpt, wor ); } } } else if ( FORM == 1 ) { /* complex ---FFT---> complex */ for ( row = 0; row < mpt; row++ ) { m = shiftr( mmin, mpt, row ); /* get data from disk */ for ( k = 0; k < nset; k++ ) { i = k * lpt; readxy( set[k], sub[k], lmin, m, &cbuf[i], lpt, 1 ); } vector( cbuf, lpt, modi, 1 ); fftx( cbuf ); wor = bitrev( row, LOGP2Y ); putrow( cbuf, 2 * lpt, wor ); } } } /* * outmap saves the result of the Fourier transform back on disk and finds * the minimum and maximum. If FORM=0 then the FFT in x is done. */ static void outmap( fint lpt , /* number of points in X */ fint mpt , /* number of points in Y */ fint lmin , /* lower x map coordinate */ fint mmin , /* lower y map coordinate */ fchar set[] , /* set name */ fint sub[] , /* subset levels */ fint nset , /* number of sets */ fint modo ) /* output mode, amp./pha. or cos./sin. */ { fint i, itab, k, m, md, mi, mj, ms, mph, mphh; fint q, r, ri, rj, rs, row; fint n; fint count[MAXSET], nblank[MAXSET]; float rbuf[2*SIZE], cbuf[2*SIZE]; float datamax[MAXSET], datamin[MAXSET]; float fr, fi, zr, zi; for ( k = 0; k < nset; count[k++] = 0 ); if ( FORM == -1 ) { /* complex ---FFT---> real */ k = 0; /* set number */ rs = MIN( mpt, ( 2 * SIZE ) / lpt ); /* number of rows per pass */ for ( r = 0 ; r < mpt; r += rs ) {/* loop to get data from scratch file */ getrow( rbuf, rs * lpt, r / rs ); md = 0; do { m = shiftr( mmin, mpt, r + md ); ms = MIN( rs - md, mpt + mmin - m ); i = md * lpt; writxy( set[k], sub[k], lmin, m, &rbuf[i], lpt, ms ); md = md + ms; } while ( md != rs ); n = lpt * rs; minmax3_c( rbuf, &n, &datamin[k], &datamax[k], &nblank[k], &count[k] ); } } else if ( FORM == 0 ) { /* real ---FFT---> complex */ q = POWTAB[ MAXP2 - LOGP2Y - 1 ]; /* table offset factor */ mph = mpt / 2; /* y-dimension of transform */ mphh = mph / 2 + 1; getrow( cbuf, 2 * lpt, 0 ); /* create row MPH */ putrow( cbuf, 2 * lpt, mph ); fr = 0.5 * SIGN; fi = 0.5; for ( ri = 0; ri < mphh; ri++ ) { rj = mph - ri; itab = ri * q; /* calculate table position */ zr = 0.5 - fr * SINTAB[itab]; zi = fi * COSTAB[itab]; getrow( cbuf, 2 * lpt, ri ); getrow( rbuf, 2 * lpt, rj ); fxrl( zr, zi, cbuf, rbuf, ri, rj, lpt ); /* fixup real ---> complex */ fftx( cbuf ); /* do the FFT in x-direction */ vector( cbuf, lpt, 1, modo ); mi = shiftr( mmin, mpt, ri ); for ( k = 0; k < nset; k++ ) { i = k * lpt; writxy( set[k], sub[k], lmin, mi, &cbuf[i], lpt , 1 ); minmax3_c( &cbuf[i], &lpt, &datamin[k], &datamax[k], &nblank[k], &count[k] ); } if ( ri > 0 ) { /* do not double lines */ mirror( cbuf, lpt, -lmin ); mi = shiftr( mmin, mpt, mpt - ri ); for ( k = 0; k < nset; k++ ) { i = k * lpt; writxy( set[k], sub[k], lmin, mi, &cbuf[i], lpt, 1 ); minmax3_c( &cbuf[i], &lpt, &datamin[k], &datamax[k], &nblank[k], &count[k] ); } } if ( ri == rj ) break; /* we've done it */ fftx( rbuf ); /* do the FFT in x-direction */ vector( rbuf, lpt, 1, modo ); mj = shiftr( mmin, mpt, rj ); for ( k = 0; k < nset; k++ ) { i = k * lpt; writxy( set[k], sub[k], lmin, mj, &rbuf[i], lpt, 1 ); minmax3_c( &rbuf[i], &lpt, &datamin[k], &datamax[k], &nblank[k], &count[k] ); } if ( rj < mph ) { /* do not double lines */ mirror( rbuf, lpt, -lmin ); mj = shiftr( mmin, mpt, mpt - rj ); for ( k = 0; k < nset; k++ ) { i = k * lpt; writxy( set[k], sub[k], lmin, mj, &rbuf[i], lpt, 1 ); minmax3_c( &rbuf[i], &lpt, &datamin[k], &datamax[k], &nblank[k], &count[k] ); } } } } else if ( FORM == 1 ) { /* complex ---FFT---> complex */ for ( row = 0; row < mpt; row++ ) { getrow( cbuf, 2 * lpt, row ); vector( cbuf, lpt, 1, modo ); m = shiftr( mmin, mpt, row ); for ( k = 0; k < nset; k++ ) { i = k * lpt; writxy( set[k], sub[k], lmin, m, &cbuf[i], lpt, 1 ); minmax3_c( &cbuf[i], &lpt, &datamin[k], &datamax[k], &nblank[k], &count[k] ); } } } { fint change = 1; fint one = 1; for ( k = 0; k < nset; k++ ) { wminmax_c( set[k], &sub[k], &datamin[k], &datamax[k], &nblank[k], &one, &change ); } } } /* * set2str converts set name to string. */ static fint set2str( char str[] , /* string */ fchar set ) /* name of set */ { fint l, n; n = nelc_c( set ); l = n - 1; while ( l >= 0 && set.a[l] != '/' ) l--; strncpy( str, &set.a[l+1], n - l - 1 ); str[n-l-1] = 0; return( n - l - 1 ); } /* * sub2str converts the coordinate word of subset to string. */ static fint sub2str( char str[] , /* string */ fchar set , /* set name */ fint sub ) /* subset level */ { fint m, n; fint naxis; fint gerror = 0; naxis = gdsc_ndims_c( set, &gerror ); strcpy( str, "(" ); m = 1; for ( n = 0; n < naxis; n++ ) { char s[10]; fint axnum = n + 1; fint grid; gerror = 0; grid = gdsc_grid_c( set, &axnum, &sub, &gerror ); if ( gerror < 0 ) { m += sprintf( s, "-," ); } else { m += sprintf( s, "%d,", grid ); } strcat( str, s ); } str[m-1] = ')'; return( m ); } /* * message generates a status message for the user. */ static void message( fchar iset[] , /* input sets */ fint isub[] , /* input subsets */ fint inset , /* number of input sets */ fchar oset[] , /* output sets */ fint osub[] , /* output subsets */ fint onset ) /* number of output sets */ { char m[1024]; fint k, l = 0; for ( k = 0; k < inset; k++ ) { if ( k ) { strcat( m, " + " ); l += 3; } l += set2str( &m[l], iset[k] ); l += sub2str( &m[l], iset[k], isub[k] ); } strcat( m, " --> " ); l += 5; for ( k = 0; k < onset; k++ ) { if ( k ) { strcat( m, " + " ); l += 3; } l += set2str( &m[l], oset[k] ); l += sub2str( &m[l], oset[k], osub[k] ); } status_c( tofchar( m ) ); } /* * main programme. */ MAIN_PROGRAM_ENTRY { char isetb[MAXSET][MAXSETNAMLEN]; char osetb[MAXSET][MAXSETNAMLEN]; fchar iset[MAXSET], oset[MAXSET]; fint lmin, lpt, mmin, mpt, modi, modo; fint isubr[MAXSUB], isubi[MAXSUB]; fint osubr[MAXSUB], osubi[MAXSUB]; fint inset, onset; fint nsub; fint k; for ( k = 0; k < MAXSET; k++ ) { fint i; iset[k].a = isetb[k]; iset[k].l = MAXSETNAMLEN; oset[k].a = osetb[k]; oset[k].l = MAXSETNAMLEN; for ( i = 0; i < MAXSETNAMLEN; i++ ) { iset[k].a[i] = ' '; oset[k].a[i] = ' '; } } setfblank_c( &BLANK ); /* get BLANK vlaue */ init_c( ); IDENTIFICATION( "FFT", VERSION ); /* * get the input from user. */ { char mes[80]; fint axperm[MAXAXES]; fint axcount[MAXAXES]; fint class = 1; fint classdim = CLASSDIM; fint cwlo, cwup; fint error_level = 4; fint gerror = 0; fint input_level; fint itab; fint items; fint maxaxes = MAXAXES; fint output_level; items = MAXSUB; input_level = 0; output_level = 11; nsub = gdsinp_c( iset[0], isubr, &items, &input_level, KEY_RINSET, MES_RINSET, &output_level, axperm, axcount, &maxaxes, &class, &classdim ); gdsc_range_c( iset[0], isubr, &cwlo, &cwup, &gerror ); lmin = gdsc_grid_c( iset[0], &axperm[0], &cwlo, &gerror ); mmin = gdsc_grid_c( iset[0], &axperm[1], &cwlo, &gerror ); lpt = axcount[0]; mpt = axcount[1]; if ( ( lpt > SIZE ) || ( mpt > SIZE ) ) { sprintf( mes, "maps are too big, maximum size is %d", SIZE ); error_c( &error_level, tofchar( mes ) ); } if ( ( lpt < 16 ) || ( mpt < 16 ) ) { sprintf( mes, "maps are too small, minimum size is 16" ); error_c( &error_level, tofchar( mes ) ); } if ( ( SIZE / lpt * lpt != SIZE ) || ( SIZE / mpt * mpt != SIZE ) ) { sprintf( mes, "size of maps must be power of two" ); error_c( &error_level, tofchar( mes ) ); } if ( ( lmin > 0 ) || (( lpt + lmin - 1) < 0 ) || ( mmin > 0 ) || ( ( mpt + mmin - 1 ) < 0 ) ) { sprintf( mes, "map does not contain 0,0" ); error_c( &error_level, tofchar( mes ) ); } items = nsub; input_level = 5; if (gdsinp_c( iset[1], isubi, &items, &input_level, KEY_IINSET, MES_IINSET, &output_level, axperm, axcount, &maxaxes, &class, &classdim )) { inset = 2; if ( lpt != axcount[0] || mpt != axcount[1] ) { sprintf( mes, "Unequal subsets sizes!" ); error_c( &error_level, tofchar( mes ) ); } if ( lmin != gdsc_grid_c( iset[1], &axperm[0], &cwlo, &gerror ) ) { sprintf( mes, "Unequal grid ranges!" ); error_c( &error_level, tofchar( mes ) ); } } else { inset = 1; } gdsasn_c( KEY_RINSET, KEY_ROUTSET, &class ); gdsasn_c( KEY_RINSET, KEY_IOUTSET, &class ); items = nsub; input_level = 4; (void) gdsout_c( oset[0], osubr, &items, &input_level, KEY_ROUTSET, MES_ROUTSET, &output_level, axperm, axcount, &maxaxes ); input_level = 5; if ( gdsout_c( oset[1], osubi, &items, &input_level, KEY_IOUTSET, MES_IOUTSET, &output_level, axperm, axcount, &maxaxes ) ) { onset = 2; } else { onset = 1; } modi = modo = 0; /* reset */ /* * Now we try to find the sign of the transform. */ input_level = 2; /* hidden keyword */ if ( inset == onset ) { if ( inset == 1 ) { /* symmetric transform (i.e.AP's) */ SIGN = 1; /* sign does not matter */ FORM = 0; /* real ---> real */ modi = 1; /* input mode is cos and sin = 0 */ modo = 1; /* output mode is cos and sin = 0 */ } else { /* complex ---> complex */ input_level = 0; /* no default */ FORM = 1; /* real+imag ---> real+imag */ } } else if ( inset == 1 ) { /* from sky to visibility ? */ SIGN = -1; /* sign is -1 */ FORM = 0; /* real ---> real+imag */ modi = 1; /* input mode is cos and sin */ } else { /* from visibility to sky */ SIGN = 1; /* sign is 1 */ FORM = -1; /* real+imag ---> real */ modo = 1; /* output mode is cos and sin */ } if ( input_level != 0 ) { sprintf( mes, "Sign of transform (1 or -1) [%d]", SIGN ); } else { sprintf( mes, "Sign of transform (1 or -1)" ); } items = 1; userint_c( &SIGN, &items, &input_level, KEY_SIGN, tofchar( mes ) ); if ( SIGN == 0 ) { sprintf( mes, "Sign cannot be zero, you ...." ); error_c( &error_level, tofchar( mes ) ); } SIGN = SIGN / labs( SIGN ); /* make it 1 or -1 */ if ( ( modi == 0 ) || ( modo == 0 ) ) { bool phase = TRUE; if ( ( modi == 0 ) && ( modo == 0 ) ) { sprintf( mes, "input/output maps in amp. and phase [Y]" ); } else if ( modi == 0 ) { sprintf( mes, "input maps in amp. and phase [Y]" ); } else if ( modo == 0 ) { sprintf( mes, "output maps in amp. and phase [Y]" ); } items = 1; input_level = 2; userlog_c( &phase, &items, &input_level, KEY_PHASE, tofchar( mes ) ); if ( !tobool( phase) ) { if ( modi == 0 ) { modi = 1; /* input is cos. and sin. */ } if ( modo == 0 ) { modo = 1; /* output is cos. and sin. */ } } else { if ( modi == 0 ) { modi = -1; /* input is amp. and pha. */ } if ( modo == 0 ) { modo = -1; /* output is amp. and pha. */ } } } input_level = 2; items = 1; (void) userreal_c( &VALUE, &items, &input_level, KEY_VALUE, MES_VALUE ); for ( itab = 0; itab < ( SIZE / 2 ); itab++ ) { COSTAB[itab] = cos( 2.0 * PI * itab / SIZE ); SINTAB[itab] = sin( 2.0 * PI * itab / SIZE ); } for ( itab = 0; itab < MAXP2; itab++ ) { POWTAB[itab]= 1 << itab; } NPTX = lpt; /* X dimension of fft */ NPTY = mpt / ( 2 - MAX( 0, FORM ) ); /* Y dimension of fft */ for ( itab = 0; itab < MAXP2; itab++ ) { if ( NPTX == ( 2 * POWTAB[itab] ) ) { LOGP2X = itab + 1; } if ( NPTY == ( 2 * POWTAB[itab] ) ) { LOGP2Y = itab + 1; } } FACTAB = sqrt( ( 0.5 * labs( 1 - 3 * FORM ) ) / (double) ( NPTX * NPTY) ); for ( itab = 0; itab < lpt; itab++ ) { XOFTAB[itab] = shiftx( -lmin, lpt, itab ); REVTAB[itab] = bitrev( itab, LOGP2X ); } } openf( lpt, mpt ); /* open scratch file */ for ( k = 0; k < nsub; k++ ) { fint isub[2], osub[2]; isub[0] = isubr[k]; isub[1] = isubi[k]; osub[0] = osubr[k]; osub[1] = osubi[k]; message( iset, isub, inset, oset, osub, onset ); inpmap( lpt, mpt, lmin, mmin, iset, isub, inset, modi ); ffty( ); outmap( lpt, mpt, lmin, mmin, oset, osub, onset, modo ); } closef( ); /* close scratch file */ finis_c( ); return( EXIT_SUCCESS ); /* return with status */ }