	SUBROUTINE FOR2D(LOG2N,NDIM,ISGN,IFORM,WORK,L2NEL,IER)
C	FOR2D COMPUTES A DISCRETE FOURIER TRANSFORM BY THE COOLEY-TUKEY
C	ALGORITHM.  IT IS WRITTEN IN ANSI BASIC FORTRAN.  THE ARRAY TO BE
C	TRANSFORMED IS COMPLEX OR REAL, MULTI-DIMENSIONAL AND KEPT ON
C	DIRECT ACCESS STORAGE.  THE NUMBER OF DATA IN EACH DIMENSION MUST
C	BE A POWER OF TWO.  RUNNING TIME IS PROPORTIONAL TO NTOT*
C	LOG2(NTOT), WHERE NTOT IS THE TOTAL NUMBER OF DATA.  (ORDINARY
C	FOURIER TRANSFORM PROGRAMS RUN IN TIME NTOT**2.)  THE TRANSFORM
C	IS DONE IN-PLACE ON THE DIRECT ACCESS STORAGE, AND AS MUCH OF THE
C	TRANSFORM AS POSSIBLE IS DONE IN CORE.  ENTIRELY IN-CORE PROGRAMS
C	ARE ALSO AVAILABLE (FOUR1, FOURG, FOUR2, FOURT AND FOURS).
C	WRITTEN BY NORMAN BRENNER, MIT AND IBM RESEARCH, SEPTEMBER 1968
C	AND JULY 1970.   SEE IEEE AUDIO AND ELECTRO-ACOUSTICS TRANSACTIONS
C	(JUNE 1967 AND JUNE 1969), SPECIAL ISSUES ON THE FAST FOURIER
C	TRANSFORM.
C
C	EFFECTIVELY, WE HAVE--
C	DIMENSION N(NDIM),LOG2N(NDIM)
C	(WHERE EACH N(I) = 2**LOG2N(I))
C	DIMENSION DATA(N(1),N(2),...,N(NDIM)),TRAN(N(1),...,N(NDIM))
C	COMPLEX DATA,TRAN
C	(DATA IS COMPLEX ONLY FOR IFORM = +1.  SEE BELOW.)
C	TRAN(K1,K2,...) = 1/SQRT(NTOT) * SUM(DATA(J1,J2,...)*EXP(ISGN*I*
C	2*PI*((J1-1)*(K1-1)/N(1)+(J2-1)*(K2-1)/N(2)+...))), SUMMED FOR ALL
C	J1 FROM 1 TO N(1), J2 FROM 1 TO N(2), ETC., FOR ALL K1 FROM 1
C	TO N(1), K2 FROM 1 TO N(2), ETC., UP TO N(NDIM).  NDIM IS
C	UNLIMITED.  IF A SET OF DATA ARE ISGN = -1 TRANSFORMED AND THEN
C	THE TRANSFORM VALUES +1 TRANSFORMED (OR VICE VERSA) THE RESULTS
C	WILL BE THE ORIGINAL DATA.  NTOT = N(1)*N(2)*...*N(NDIM).
C	IFORM = +1, 0 OR -1, ACCORDING AS DATA ARE COMPLEX, REAL OR THE
C	TRANSFORM OF REAL (CONJUGATE-SYMMETRIC COMPLEX).  THE LAST TWO
C	CASES NEED ONLY HALF THE SPACE AND HALF THE RUNNING TIME OF THE
C	FIRST CASE.
C
C	IN ACTUALITY, THE DATA ARRAY IS STORED ON A DIRECT ACCESS
C	STORAGE DEVICE (DISK, DRUM OR DATA CELL).
C	ELEMENTS ARE ARRANGED IN COLUMN-MAJOR ORDER (FIRST SUBSCRIPT
C	INCREASING FASTEST), BROKEN INTO LOGICAL RECORDS OF LENGTH NELEM
C	= 2**L2NEL COMPLEX ELEMENTS.  EACH LOGICAL RECORD IS COMPOSED
C	OF ONE OR MORE PHYSICAL RECORDS, THE LATTER TYPICALLY FITTING
C	INTO ONE TRACK.  FOR FASTEST RUNNING TIME, MAKE NELEM AS LARGE
C	AS POSSIBLE.  TRANSFORM VALUES ARE RETURNED TO FILE ICHAN,
C	REPLACING THE INPUT.  CONSIDER AN INPUT ARRAY DATA OF DIMENSIONS
C	N1 BY N2.  IF IFORM = +1, BOTH INPUT AND OUTPUT ARE COMPLEX N1
C	BY N2, AND COMPRISE FILE ICHAN, RECORD NUMBERS 1 TO (N1*N2)/NELEM.
C	IF IFORM = 0, THE INPUT ARRAY IS REAL N1 BY N2, AND OCCUPIES
C	RECORD NUMBERS 1 TO (N1*N2/2)/NELEM, SINCE REAL NUMBERS TAKE ONLY
C	HALF THE SPACE OF COMPLEX ONES.  NELEM, THO, IS STILL GIVEN AS THE
C	NUMBER OF COMPLEX ELEMENTS ONE LOGICAL RECORD CAN HOLD.  THE OUT-
C	PUT TRANSFORM ARRAY IS COMPLEX N1/2+1 BY N2.  ROWS 1 TO N1/2 ARE
C	PLACED IN RECORDS 1 TO (N1*N2/2)/NELEM, WHILE ROW N1/2+1 BEGINS
C	IN THE RECORD IMMEDIATELY FOLLOWING.  THUS, THE TRANSFORM OF A
C	REAL ARRAY TAKES UP SLIGHTLY MORE SPACE THAN THE INPUT.  THE
C	MISSING LOWER HALF IS OF COURSE REDUNDANT, BEING THE COMPLEX
C	CONJUGATE OF THE UPPER HALF.  THE INPUT IS ARRANGED IN THE ORDER
C	DATA(1,1), DATA(2,1), ..., DATA(N1,1), DATA(1,2),..., DATA(N1,N2).
C	THE OUTPUT IS ARRANGED AS TRAN(1,1), ..., TRAN(N1/2,1), TRAN(2,1),
C	..., TRAN(N1/2,N2), TRAN(N1/2+1,1), ..., TRAN(N1/2+1,N2).  FOR
C	IFORM = -1, THE INPUT IS COMPLEX N1/2+1 BY N2, ARRANGED AS SHOWN,
C	AND THE OUTPUT IS REAL N1 BY N2.  IN GENERAL, MULTI-DIMENSIONAL
C	REAL ARRAYS N1 BY N2 BY ... TRANSFORM INTO COMPLEX ARRAYS N1/2+1
C	BY N2 BY ..., ARRANGED AS SHOWN.
C
C	THE INPUT FILE MUST BE CONTIGUOUS
C	NELEM MUST BE NO LARGER THAN 4096 DUE TO SUBSCRIPTING LIMITATIONS
C
	DIMENSION LOG2N(1),WORK(1)

	IF (IABS(NDIM-1)-NDIM+1+IABS(IABS(ISGN)-1)+IABS(IFORM)/2
     *  +IABS(L2NEL)-L2NEL) 5,5,230
5	L2TOT=0
	DO 10 IDIMX=1,NDIM
	IF (LOG2N(IDIMX)) 250,10,10
10	L2TOT=L2TOT+LOG2N(IDIMX)
	NRECT=1
	IF (L2TOT-(2-IFORM)/2-L2NEL) 30,30,20
20	NRECT=2**(L2TOT-(2-IFORM)/2-L2NEL)
30	NRTEX=1
	IF (L2TOT-LOG2N(1)-L2NEL) 50,50,40
40	NRTEX=2**(L2TOT-LOG2N(1)-L2NEL)
50	NELEM=2**L2NEL
	L2REM=L2TOT
	IF (IFORM) 60,70,70
60	L2REM=0
	L2TOT=L2TOT-1
70	DO 220 JDIM=1,NDIM
	IF (IFORM) 80,90,90
80	IDIMX=NDIM+1-JDIM
	GO TO 100
90	IDIMX=JDIM
	L2REM=L2REM-LOG2N(IDIMX)
100	L2CUR=LOG2N(IDIMX)
	IF (IDIMX-1) 110,110,140
110	IF (IFORM) 120,130,140
C	FIX UP A CONJUGATE SYMMETRIC ARRAY TO LOOK LIKE COMPLEX
120	CALL FXRLD(LOG2N,L2REM,ISGN,IFORM,WORK,L2NEL,NELEM,
     *	NRECT)
	L2TOT=L2TOT+1
130	L2CUR=L2CUR-1
140	L2PRV=L2TOT-L2REM-LOG2N(IDIMX)
	IF (L2CUR) 160,160,150
C	REARRANGE THE DATA BY BIT REVERSAL ALONG ONE DIMENSION
150	CALL BTRVD(L2PRV,L2CUR,L2REM,ISGN,WORK,L2NEL,NELEM,NRECT,0,
     *	LOG2N(IDIMX))
C	COMPUTE THE DISCRETE FOURIER TRANSFORM ALONG ONE DIMENSION
	CALL DFT2D(L2PRV,L2CUR,L2REM,ISGN,WORK,L2NEL,NELEM,NRECT,0)
160	IF (IFORM) 170,170,220
170	IF (IDIMX-1) 190,190,180
C	REARRANGE AND TRANSFORM THE N1/2+1'ST ROW
180	CALL BTRVD(L2PRV-LOG2N(1)+1,L2CUR,L2REM,ISGN,WORK,L2NEL,
     *  NELEM,NRTEX,NRECT,LOG2N(IDIMX))
	CALL DFT2D(L2PRV-LOG2N(1)+1,L2CUR,L2REM,ISGN,WORK,L2NEL,
     *  NELEM,NRTEX,NRECT)
190	IF ((IFORM+1)*IDIMX-1) 200,210,220
200	L2REM=L2REM+LOG2N(IDIMX)
	GO TO 220
C	FIX UP THE TRANSFORM OF A REAL ARRAY
210	CALL FXRLD(LOG2N,L2REM,ISGN,IFORM,WORK,L2NEL,NELEM,
     *  NRECT)
	L2TOT=L2TOT-1
220	CONTINUE
	IER=0
260	CONTINUE
	RETURN

230	IER=1
	GO TO 260
250	IER=2
	GO TO 260
	END
