17#include "scaleFElib.h"
26 use scale_const,
only: &
27 undef8 => const_undef8, &
41 complex(RP),
allocatable :: w_forward(:)
42 complex(RP),
allocatable :: w_backward(:)
45 logical :: use_bluestein
46 complex(RP),
allocatable :: w1_bluestein(:)
47 complex(RP),
allocatable :: w2_bluestein(:)
51 procedure :: final => fastfouriertransform1d_final
52 procedure :: forward_cmplx => fastfouriertransform1d_forward_cmplx
53 procedure :: forward_real => fastfouriertransform1d_forward_real
54 generic :: forward => forward_cmplx, forward_real
55 procedure :: backward => fastfouriertransform1d_backward
77 integer,
intent(in) :: N
91 jj = cmplx( 0.0_rp, 1.0_rp )
94 if ( is_power_of_two(n) )
then
95 this%use_bluestein = .false.
97 log_info(
"FastFourierTransform1D_Init",*)
"use_bluestein=F"
98 log_info(
"FastFourierTransform1D_Init",*)
"MM=", mm
100 this%use_bluestein = .true.
102 do while ( m < 2*n-1 )
106 log_info(
"FastFourierTransform1D_Init",*)
"use_bluestein=T"
107 log_info(
"FastFourierTransform1D_Init",*)
"M=", m,
"MM=", mm
111 allocate( this%W_forward(mm), this%W_backward(mm) )
113 angle0 = 2.0_rp * pi / real(2*mm, kind=rp)
116 angle = angle0 * real(k, kind=rp)
117 this%W_forward (k+1) = exp(- jj * angle )
118 this%W_backward(k+1) = exp( jj * angle )
121 if ( this%use_bluestein )
then
122 allocate( this%W1_bluestein(n), this%W2_bluestein(n) )
125 angle = pi * real(k*k,kind=rp) / real(n, kind=rp)
126 this%W1_bluestein(k+1) = exp(- jj * angle )
127 this%W2_bluestein(k+1) = exp( jj * angle )
135 subroutine fastfouriertransform1d_forward_real( this, q, s )
138 real(RP),
intent(in) :: q(this%N)
139 complex(RP),
intent(out) :: s(this%N)
141 complex(RP) :: q_(this%N)
146 q_(i) = cmplx(q(i), 0.0_rp, kind=rp)
148 call this%Forward_cmplx( q_, s )
150 end subroutine fastfouriertransform1d_forward_real
153 subroutine fastfouriertransform1d_forward_cmplx( this, q, s )
156 complex(RP),
intent(in) :: q(this%N)
157 complex(RP),
intent(out) :: s(this%N)
163 if ( this%use_bluestein )
then
164 call fft1d_bluestein( s, &
165 q, this%W_forward, this%W_backward, this%W1_bluestein, this%W2_bluestein, &
168 call fft1d_norecursive_core( s, &
169 q, this%W_forward, this%N )
174 scaling = 1.0_rp / real( this%N )
175 s(:) = scaling * s(:)
177 end subroutine fastfouriertransform1d_forward_cmplx
180 subroutine fastfouriertransform1d_backward( this, s, q )
183 complex(RP),
intent(in) :: s(this%N)
184 real(RP),
intent(out) :: q(this%N)
186 complex(RP) :: q_(this%N)
190 if ( this%use_bluestein )
then
191 call fft1d_bluestein( q_, &
192 s, this%W_forward, this%W_backward, this%W2_bluestein, this%W1_bluestein, &
195 call fft1d_norecursive_core( q_, &
196 s, this%W_backward, this%N )
200 q(i) = real(q_(i), kind=rp)
203 end subroutine fastfouriertransform1d_backward
206 subroutine fastfouriertransform1d_final( this )
211 deallocate( this%W_forward, this%W_backward)
213 if ( this%use_bluestein )
then
214 deallocate( this%W1_bluestein, this%W2_bluestein )
217 end subroutine fastfouriertransform1d_final
221 subroutine fft1d_bluestein( x_out, x_in, W_forward, W_backward, W1, W2, N, M )
223 integer,
intent(in) :: N, M
224 complex(RP),
intent(out) :: x_out(N)
225 complex(RP),
intent(in) :: x_in(N)
226 complex(RP),
intent(in) :: W_forward(M/2)
227 complex(RP),
intent(in) :: W_backward(M/2)
228 complex(RP),
intent(in) :: W1(N)
229 complex(RP),
intent(in) :: W2(N)
231 complex(RP) :: a(M), b(M)
232 complex(RP) :: AA(M), BB(M), CC(M)
241 a(i+1) = x_in(i+1) * w1(i+1)
251 call fft1d_norecursive_core( aa, &
253 call fft1d_norecursive_core( bb, &
256 call fft1d_norecursive_core( cc, &
257 aa(:) * bb(:), w_backward, m )
260 scaling = 1.0_rp / real( m )
262 x_out(i) = scaling * cc(i) * w1(i)
265 end subroutine fft1d_bluestein
268 subroutine fft1d_norecursive_core( x_out, x_in, W, N )
270 integer,
intent(in) :: N
271 complex(RP),
intent(out) :: x_out(N)
272 complex(RP),
intent(in) :: x_in(N)
273 complex(RP),
intent(in) :: W(N/2)
277 complex(RP) :: tmp(N)
294 nbits = int( log(real(n,kind=rp)) / log(2.0_rp) + 0.5_rp )
298 if ( i/2**j - 2*(i/2**(j+1)) == 1 ) rev = rev + 2**(nbits-j-1)
300 x_out(rev+1) = tmp(i+1)
311 t = w(ind+1) * x_out(k+j+m+1)
313 x_out(k+j+1 ) = u + t
314 x_out(k+j+1+m) = u - t
320 end subroutine fft1d_norecursive_core
323 recursive subroutine fft1d_recursive_core( x_out, x_in, W, N, N0 )
325 integer,
intent(in) :: N
326 integer,
intent(in) :: N0
327 complex(RP),
intent(out) :: x_out(N)
328 complex(RP),
intent(in) :: x_in(N)
329 complex(RP),
intent(in) :: W(N0/2)
331 complex(RP) :: even(N/2), odd(N/2)
332 complex(RP) :: E(N/2), O(N/2)
336 complex(RP) :: twiddle
344 even(:) = x_in(1:n:2)
347 call fft1d_recursive_core( e, &
349 call fft1d_recursive_core( o, &
354 x_out(k+1 ) = e(k+1) + w(s*k+1) * o(k+1)
355 x_out(k+1+n/2) = e(k+1) - w(s*k+1) * o(k+1)
358 end subroutine fft1d_recursive_core
361 logical function is_power_of_two(N)
363 integer,
intent(in) :: N
365 is_power_of_two = (n > 0) .and. (iand(n, n-1) == 0)
367 end function is_power_of_two