1C    -------------------------------------------------------------------------
  2C    |  File name:   fftd.for              Sean O'Connor             9-22-87 |
  3C    |                                                               7-01-17 |
  4C    ------------------------------------------------------------------------- 
  5
  6C    -------------------------------------------------------------------------
  7C    |  VAX 11/785       VMS 4.5                   VAX EXTENDED FORTRAN 77   |
  8C    |  MacBook Pro      Ubuntu LTS 16.04 Linux    gfortran                  |
  9C    -------------------------------------------------------------------------
 10
 11
 12C  ****************************************************************************
 13C  *                                                                          *
 14C  *                            FFTD                                          *
 15C  *                                                                          *
 16C  ****************************************************************************
 17C
 18C
 19C  DESCRIPTION
 20C 
 21C      This program tests the subroutine FFT in the file FFT.FOR  It does a 
 22C      forward discrete Fourier transform (DFT).  It then does an inverse
 23C      transform of the forward transform to check the roundoff error.
 24C
 25C
 26C  INPUT 
 27C
 28C      The number of complex points in the transform.
 29C      Whether to do a forward (1) or inverse (-1) transform.
 30C      The data points (complex numbers).
 31C
 32C
 33C  OUTPUT
 34C
 35C      The DFT of the input.
 36C      The inverse DFT of the first DFT.
 37C
 38C
 39C  EXAMPLE 
 40C
 41C      $ ./FFTD
 42C
 43C      Enter number of complex points in transform: 4
 44C
 45C      Enter 1 (forward) or -1 (inverse) transform:  1
 46C
 47C      Enter point no.   0 (Real, Imag) >  (1,1)
 48C      Enter point no.   1 (Real, Imag) >  (2,2)
 49C      Enter point no.   2 (Real, Imag) >  (3,3)
 50C      Enter point no.   3 (Real, Imag) >  (4,4)
 51C
 52C      num_points =          4
 53C      direction  =          1
 54C
 55C      Point No.   0 = (   1.0000000000000       1.0000000000000     ) 
 56C      Point No.   1 = (   2.0000000000000       2.0000000000000     ) 
 57C      Point No.   2 = (   3.0000000000000       3.0000000000000     ) 
 58C      Point No.   3 = (   4.0000000000000       4.0000000000000     ) 
 59C
 60C      The transform of the input is . . .
 61C 
 62C      Point No.   0= (  5.0000000000000       5.0000000000000     ) 
 63C      Point No.   1= ( -2.0000000000000      0.00000000000000E+000) 
 64C      Point No.   2= ( -1.0000000000000      -1.0000000000000     ) 
 65C      Point No.   3= (-0.59604644775391E-007 -2.0000000000000     ) 
 66C
 67C      The inverse transform of the transform above is . . .
 68C  
 69C      Point No.   0= (  1.0000000000000       1.0000000000000     ) 
 70C      Point No.   1= (  2.0000000000000       2.0000000000000     ) 
 71C      Point No.   2= (  3.0000000000000       3.0000000000000     ) 
 72C      Point No.   3= (  4.0000000000000       4.0000000000000     ) 
 73C
 74C
 75C  INSTALLATION
 76C
 77C      To compile, type
 78C
 79C          $ gfortran FFTD.FOR FORTRAN FFT.FOR -o FFT
 80C
 81C      To run, type
 82C
 83C          $ ./FFTD
 84C       
 85C 
 86C  ****************************************************************************
 87C  *                                                                          *
 88C  ****************************************************************************
 89
 90      PROGRAM fftd
 91
 92C  -------------------------------------------------------------------------
 93C  |                            MACRO DEFINITIONS                          |
 94C  ------------------------------------------------------------------------- 
 95
 96      PARAMETER ( MAX_NUM_POINTS = 255 )   !  Maximum number of points in FFT.
 97
 98
 99C -------------------------------------------------------------------------
100C |                          LOCAL VARIABLES                              |
101C -------------------------------------------------------------------------
102
103        INTEGER i,             !  Loop counter
104     $          num_points,    !  Number of points in the transform
105     $          direction      !  Direction of transform 1 for forward,
106                               ! -1 for inverse
107
108        COMPLEX X( 0 : MAX_NUM_POINTS )  !  Array of complex data points
109                                         !  to be transformed.
110
111
112C -------------------------------------------------------------------------
113C |                          PROGRAM CODE                                 |
114C -------------------------------------------------------------------------
115
116C
117C    Read the number of points in the FFT
118C
119        WRITE( 6, 100 )
120100     FORMAT ( ' Enter number of complex points in transform:  ' )
121
122        READ ( 5 , * ) num_points      ! Free format input
123
124
125
126C
127C       Decide whether to do the forward or inverse FFT
128C
129
130        WRITE( 6, 200 )
131200     FORMAT ( //, ' Enter 1 for a forward transform ', /,
132     $               ' or -1 for an inverse transform: ' )
133
134        READ ( 5, * ) direction     ! Free format input
135
136
137C
138C       Check to see that the number of points in the FFT
139C       is valid.  If not, halt.
140C
141
142        IF ( (num_points .LE. 0) .OR. 
143     $       (num_points .GT. MAX_NUM_POINTS) ) THEN
144                
145                WRITE( 6, 300 )
146300             FORMAT( ' The number of points is out of range ')
147                STOP
148        
149        END IF
150
151
152
153C
154C       Read in the complex data points, one by one 
155C
156        DO i = 0, num_points - 1
157
158            WRITE( 6, 400 ) i
159400         FORMAT ( ' Enter point no. ', I3,' (Real, Imag) > ')
160            READ ( 5 , * ) X( i )      ! Free format input
161
162        END DO
163
164
165C
166C       Print out the points just read in.
167C
168
169        WRITE( 6, 500 ) num_points
170500     FORMAT ( //, ' num_points = ', I10, / )
171
172        WRITE( 6, 600 ) direction
173600     FORMAT ( ' direction =  ', I10, // )
174
175        DO i = 0, num_points - 1
176                
177            WRITE( 6 , 700 ) i , X ( i )
178700         FORMAT ( ' Point no. ', I3, ' = ( ', 2G22.14E3, ') ' )
179
180        END DO
181
182
183C
184C       Call the FFT subroutine.
185C
186        CALL FFT( num_points, X, direction )
187
188
189C
190C       Print the transform results.
191C
192        WRITE( 6, 800 )
193800     FORMAT ( //, ' The transform of the input data is . . . ', // )
194
195
196        DO i = 0, num_points - 1
197                
198            WRITE( 6, 900 ) i , X( i )
199900         FORMAT (' Point No. ', I3, '= (', 2G22.14E3, ') ' )
200
201        END DO
202
203
204C
205C       Call the FFT subroutine with -direction to do the inverse transform.
206C
207        CALL FFT( num_points, X, -direction )
208
209
210
211C
212C       Print the inverse transform coefficients.
213C
214        WRITE ( 6, 1000 )
2151000    FORMAT ( //,' The inverse transform ',
216     $               'of the transform above is . . .', // )
217
218
219        DO i = 0, num_points - 1
220                
221            WRITE ( 6, 1100 ) i , X( i )
2221100        FORMAT (' Point No. ', I3, '= (', 2G22.14E3, ') ' )
223
224        END DO
225
226
227
228C
229C  Test the error checking in the FFT routine.
230C
231
232C  Number of points is too large.  Currently, MAX_TABLE_SIZE in
233C  subroutine FFT is 20, so we can transform up to 2 ** 21 points.
234
235        PRINT *, ' Calling FFT with too many points.'
236
237        CALL FFT( 2 ** 22, X, 1 )
238
239
240C  Number of points is less than 2.
241
242        PRINT *, ' Calling FFT with 1 point.'
243
244        CALL FFT( 1, X, 1 )
245
246
247C  Calling FFT with 2^ 15 + 1 points (not a power of 2)
248
249        PRINT *, ' Calling FFT with 2 ^ 15 + 1 points'
250
251        CALL FFT( 2 * 15 + 1, X, 1 )
252
253
254C  Direction is not 1 or -1.
255
256        PRINT *, ' Calling FFT with direction = 2'
257
258        CALL FFT( 16, X, 2)
259
260
261        STOP
262        END   ! of program fftd