MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_fft.t
Go to the documentation of this file.
1!> Self-contained complex FFT utilities based on the mixed-radix Singleton
2!> transform historically embedded in mod_pfss.
3module mod_fft
4 implicit none
5 private
6
7 public :: fft_1d
8 public :: fft_2d
9 public :: fft_2d_real_imag
10 public :: fft_raw
11 public :: fft_size_supported
12 public :: fft_next_supported
13 public :: fft_factorization
14
15contains
16
17 !> Return whether the legacy mixed-radix workspace can handle a transform.
18 logical function fft_size_supported(n)
19 integer, intent(in) :: n
20 integer :: m,p,nleft,nfactors,square_free
21
22 if(n<1) then
23 fft_size_supported=.false.
24 return
25 end if
26
27 nleft=n
28 nfactors=0
29 square_free=1
30 p=2
31 do while(p*p<=nleft)
32 if(mod(nleft,p)==0) then
33 if(p>23) then
34 fft_size_supported=.false.
35 return
36 end if
37 square_free=square_free*p
38 do while(mod(nleft,p)==0)
39 nleft=nleft/p
40 nfactors=nfactors+1
41 end do
42 end if
43 if(p==2) then
44 p=3
45 else
46 p=p+2
47 end if
48 end do
49 if(nleft>1) then
50 if(nleft>23) then
51 fft_size_supported=.false.
52 return
53 end if
54 square_free=square_free*nleft
55 nfactors=nfactors+1
56 end if
57
58 ! The embedded algorithm stores at most 11 factors and 209 permutation
59 ! entries. Repeated powers of two are combined internally, so this check is
60 ! deliberately conservative only for the general prime-factor path.
61 m=n
62 nfactors=0
63 do p=2,23
64 do while(mod(m,p)==0)
65 m=m/p
66 nfactors=nfactors+1
67 end do
68 end do
69 fft_size_supported=(m==1 .and. nfactors<=11 .and. square_free<=210)
70 end function fft_size_supported
71
72 integer function fft_next_supported(n)
73 integer, intent(in) :: n
74
75 fft_next_supported=max(1,n)
78 end do
79 end function fft_next_supported
80
81 !> Human-readable prime factorization used in unsupported-size diagnostics.
82 function fft_factorization(n) result(description)
83 integer, intent(in) :: n
84 character(len=128) :: description
85 character(len=24) :: item
86 integer :: left,p,power,used
87
88 description=''
89 if(n<1) then
90 write(description,'(i0)') n
91 return
92 end if
93
94 left=n
95 p=2
96 used=0
97 do while(p*p<=left)
98 power=0
99 do while(mod(left,p)==0)
100 left=left/p
101 power=power+1
102 end do
103 if(power>0) then
104 if(power==1) then
105 write(item,'(i0)') p
106 else
107 write(item,'(i0,a,i0)') p,'^',power
108 end if
109 if(used>0) description=trim(description)//' * '
110 description=trim(description)//trim(item)
111 used=used+1
112 end if
113 if(p==2) then
114 p=3
115 else
116 p=p+2
117 end if
118 end do
119 if(left>1) then
120 write(item,'(i0)') left
121 if(used>0) description=trim(description)//' * '
122 description=trim(description)//trim(item)
123 end if
124 if(len_trim(description)==0) description='1'
125 end function fft_factorization
126
127 !> In-place complex one-dimensional FFT. The inverse is normalized.
128 subroutine fft_1d(data,inverse)
129 double complex, intent(inout) :: data(:)
130 logical, intent(in) :: inverse
131 double precision, allocatable :: ar(:),ai(:)
132 integer :: n,isign
133
134 n=size(data)
135 if(.not.fft_size_supported(n)) error stop 'fft_1d: unsupported transform size'
136 allocate(ar(n),ai(n))
137 ar=dble(data)
138 ai=dimag(data)
139 if(inverse) then
140 isign=1
141 else
142 isign=-1
143 end if
144 call fft_raw(ar,ai,n,n,n,isign)
145 data=dcmplx(ar,ai)
146 if(inverse) data=data/dble(n)
147 deallocate(ar,ai)
148 end subroutine fft_1d
149
150 !> In-place complex two-dimensional FFT. The inverse is normalized.
151 subroutine fft_2d(data,inverse)
152 double complex, intent(inout) :: data(:,:)
153 logical, intent(in) :: inverse
154 double precision, allocatable :: ar(:),ai(:)
155 integer :: n1,n2,ntot,isign
156
157 n1=size(data,1)
158 n2=size(data,2)
159 if(.not.fft_size_supported(n1) .or. .not.fft_size_supported(n2)) &
160 error stop 'fft_2d: unsupported transform size'
161
162 ntot=n1*n2
163 allocate(ar(ntot),ai(ntot))
164 ar=reshape(dble(data),[ntot])
165 ai=reshape(dimag(data),[ntot])
166 if(inverse) then
167 isign=1
168 else
169 isign=-1
170 end if
171 call fft_raw(ar,ai,ntot,n1,n1,isign)
172 call fft_raw(ar,ai,ntot,n2,ntot,isign)
173 data=reshape(dcmplx(ar,ai),shape(data))
174 if(inverse) data=data/dble(ntot)
175 deallocate(ar,ai)
176 end subroutine fft_2d
177
178 !> In-place two-dimensional FFT on split real/imaginary storage. This avoids
179 !> allocation and copying in repeated plane transforms.
180 subroutine fft_2d_real_imag(ar,ai,inverse)
181 double precision, intent(inout) :: ar(:,:),ai(:,:)
182 logical, intent(in) :: inverse
183 integer :: n1,n2,ntot,isign
184
185 n1=size(ar,1)
186 n2=size(ar,2)
187 if(any(shape(ai)/=shape(ar))) error stop 'fft_2d_real_imag: shape mismatch'
188 if(.not.fft_size_supported(n1) .or. .not.fft_size_supported(n2)) &
189 error stop 'fft_2d_real_imag: unsupported transform size'
190
191 ntot=n1*n2
192 if(inverse) then
193 isign=1
194 else
195 isign=-1
196 end if
197 call fft_raw(ar,ai,ntot,n1,n1,isign)
198 call fft_raw(ar,ai,ntot,n2,ntot,isign)
199 if(inverse) then
200 ar=ar/dble(ntot)
201 ai=ai/dble(ntot)
202 end if
203 end subroutine fft_2d_real_imag
204
205 subroutine fft_raw(a,b,ntot,n,nspan,isn)
206 ! multivariate complex fourier transform, computed in place
207 ! using mixed-radix fast fourier transform algorithm.
208 ! by r. c. singleton, stanford research institute, sept. 1968
209 ! arrays a and b originally hold the real and imaginary
210 ! components of the data, and return the real and
211 ! imaginary components of the resulting fourier coefficients.
212 ! multivariate data is indexed according to the fortran
213 ! array element successor function, without limit
214 ! on the number of implied multiple subscripts.
215 ! the subroutine is called once for each variate.
216 ! the calls for a multivariate transform may be in any order.
217 ! ntot is the total number of complex data values.
218 ! n is the dimension of the current variable.
219 ! nspan/n is the spacing of consecutive data values
220 ! while indexing the current variable.
221 ! the sign of isn determines the sign of the complex
222 ! exponential, and the magnitude of isn is normally one.
223 ! a tri-variate transform with a(n1,n2,n3), b(n1,n2,n3)
224 ! is computed by
225 ! call fft(a,b,n1*n2*n3,n1,n1,1)
226 ! call fft(a,b,n1*n2*n3,n2,n1*n2,1)
227 ! call fft(a,b,n1*n2*n3,n3,n1*n2*n3,1)
228 ! for a single-variate transform,
229 ! ntot = n = nspan = (number of complex data values), e.g.
230 ! call fft(a,b,n,n,n,1)
231 ! the data can alternatively be stored in a single complex array c
232 ! in standard fortran fashion, i.e. alternating real and imaginary
233 ! parts. then with most fortran compilers, the complex array c can
234 ! be equivalenced to a real array a, the magnitude of isn changed
235 ! to two to give correct indexing increment, and a(1) and a(2) used
236 ! to pass the initial addresses for the sequences of real and
237 ! imaginary values, e.g.
238 ! complex c(ntot)
239 ! real a(2*ntot)
240 ! equivalence (c(1),a(1))
241 ! call fft(a(1),a(2),ntot,n,nspan,2)
242 ! arrays at(maxf), ck(maxf), bt(maxf), sk(maxf), and np(maxp)
243 ! are used for temporary storage. if the available storage
244 ! is insufficient, the program is terminated by a stop.
245 ! maxf must be .ge. the maximum prime factor of n.
246 ! maxp must be .gt. the number of prime factors of n.
247 ! in addition, if the square-free portion k of n has two or
248 ! more prime factors, then maxp must be .ge. k-1.
249 double precision :: a(*),b(*)
250 ! array storage in nfac for a maximum of 15 prime factors of n.
251 ! if n has more than one square-free factor, the product of the
252 ! square-free factors must be .le. 210
253 dimension nfac(11),np(209)
254 ! array storage for maximum prime factor of 23
255 dimension at(23),ck(23),bt(23),sk(23)
256 double precision :: c72,s72,s120,rad,radf,sd,cd,ak,bk,c1
257 double precision :: s1,aj,bj,akp,ajp,ajm,akm,bkp,bkm,bjp,bjm,aa
258 double precision :: bb,sk,ck,at,bt,s3,c3,s2,c2
259 integer :: i,ii,maxp,maxf,n,inc,isn,nt,ntot,ks,nspan,kspan,nn,jc,jf,m
260 integer :: k,j,jj,nfac,kt,np,kk,k1,k2,k3,k4,kspnn
261 equivalence(i,ii)
262
263 ! the following two constants should agree with the array dimensions.
264 maxp=209
265 ! Date: Wed, 9 Aug 1995 09:38:49 -0400
266 ! From: ldm@apollo.numis.nwu.edu
267 maxf=23
268 s3=0.d0
269 s2=0.d0
270 c3=0.d0
271 c2=0.d0
272 if(n .lt. 2) return
273 inc=isn
274 c72=0.30901699437494742d0
275 s72=0.95105651629515357d0
276 s120=0.86602540378443865d0
277 rad=6.2831853071796d0
278 if(isn .ge. 0) go to 10
279 s72=-s72
280 s120=-s120
281 rad=-rad
282 inc=-inc
283 10 nt=inc*ntot
284 ks=inc*nspan
285 kspan=ks
286 nn=nt-inc
287 jc=ks/n
288 radf=rad*dble(jc)*0.5d0
289 i=0
290 jf=0
291 ! determine the factors of n
292 m=0
293 k=n
294 go to 20
295 15 m=m+1
296 nfac(m)=4
297 k=k/16
298 20 if(k-(k/16)*16 .eq. 0) go to 15
299 j=3
300 jj=9
301 go to 30
302 25 m=m+1
303 nfac(m)=j
304 k=k/jj
305 30 if(mod(k,jj) .eq. 0) go to 25
306 j=j+2
307 jj=j**2
308 if(jj .le. k) go to 30
309 if(k .gt. 4) go to 40
310 kt=m
311 nfac(m+1)=k
312 if(k .ne. 1) m=m+1
313 go to 80
314 40 if(k-(k/4)*4 .ne. 0) go to 50
315 m=m+1
316 nfac(m)=2
317 k=k/4
318 50 kt=m
319 j=2
320 60 if(mod(k,j) .ne. 0) go to 70
321 m=m+1
322 nfac(m)=j
323 k=k/j
324 70 j=((j+1)/2)*2+1
325 if(j .le. k) go to 60
326 80 if(kt .eq. 0) go to 100
327 j=kt
328 90 m=m+1
329 nfac(m)=nfac(j)
330 j=j-1
331 if(j .ne. 0) go to 90
332 ! compute fourier transform
333 100 sd=radf/dble(kspan)
334 cd=2.d0*dsin(sd)**2
335 sd=dsin(sd+sd)
336 kk=1
337 i=i+1
338 if(nfac(i) .ne. 2) go to 400
339 ! transform for factor of 2 (including rotation factor)
340 kspan=kspan/2
341 k1=kspan+2
342 210 k2=kk+kspan
343 ak=a(k2)
344 bk=b(k2)
345 a(k2)=a(kk)-ak
346 b(k2)=b(kk)-bk
347 a(kk)=a(kk)+ak
348 b(kk)=b(kk)+bk
349 kk=k2+kspan
350 if(kk .le. nn) go to 210
351 kk=kk-nn
352 if(kk .le. jc) go to 210
353 if(kk .gt. kspan) go to 800
354 220 c1=1.d0-cd
355 s1=sd
356 230 k2=kk+kspan
357 ak=a(kk)-a(k2)
358 bk=b(kk)-b(k2)
359 a(kk)=a(kk)+a(k2)
360 b(kk)=b(kk)+b(k2)
361 a(k2)=c1*ak-s1*bk
362 b(k2)=s1*ak+c1*bk
363 kk=k2+kspan
364 if(kk .lt. nt) go to 230
365 k2=kk-nt
366 c1=-c1
367 kk=k1-k2
368 if(kk .gt. k2) go to 230
369 ak=c1-(cd*c1+sd*s1)
370 s1=(sd*c1-cd*s1)+s1
371 c1=2.d0-(ak**2+s1**2)
372 s1=c1*s1
373 c1=c1*ak
374 kk=kk+jc
375 if(kk .lt. k2) go to 230
376 k1=k1+inc+inc
377 kk=(k1-kspan)/2+jc
378 if(kk .le. jc+jc) go to 220
379 go to 100
380 ! transform for factor of 3 (optional code)
381 320 k1=kk+kspan
382 k2=k1+kspan
383 ak=a(kk)
384 bk=b(kk)
385 aj=a(k1)+a(k2)
386 bj=b(k1)+b(k2)
387 a(kk)=ak+aj
388 b(kk)=bk+bj
389 ak=-0.5d0*aj+ak
390 bk=-0.5d0*bj+bk
391 aj=(a(k1)-a(k2))*s120
392 bj=(b(k1)-b(k2))*s120
393 a(k1)=ak-bj
394 b(k1)=bk+aj
395 a(k2)=ak+bj
396 b(k2)=bk-aj
397 kk=k2+kspan
398 if(kk .lt. nn) go to 320
399 kk=kk-nn
400 if(kk .le. kspan) go to 320
401 go to 700
402 ! transform for factor of 4
403 400 if(nfac(i) .ne. 4) go to 600
404 kspnn=kspan
405 kspan=kspan/4
406 410 c1=1.d0
407 s1=0.d0
408 420 k1=kk+kspan
409 k2=k1+kspan
410 k3=k2+kspan
411 akp=a(kk)+a(k2)
412 akm=a(kk)-a(k2)
413 ajp=a(k1)+a(k3)
414 ajm=a(k1)-a(k3)
415 a(kk)=akp+ajp
416 ajp=akp-ajp
417 bkp=b(kk)+b(k2)
418 bkm=b(kk)-b(k2)
419 bjp=b(k1)+b(k3)
420 bjm=b(k1)-b(k3)
421 b(kk)=bkp+bjp
422 bjp=bkp-bjp
423 if(isn .lt. 0) go to 450
424 akp=akm-bjm
425 akm=akm+bjm
426 bkp=bkm+ajm
427 bkm=bkm-ajm
428 if(s1 .eq. 0.d0) go to 460
429 430 a(k1)=akp*c1-bkp*s1
430 b(k1)=akp*s1+bkp*c1
431 a(k2)=ajp*c2-bjp*s2
432 b(k2)=ajp*s2+bjp*c2
433 a(k3)=akm*c3-bkm*s3
434 b(k3)=akm*s3+bkm*c3
435 kk=k3+kspan
436 if(kk .le. nt) go to 420
437 440 c2=c1-(cd*c1+sd*s1)
438 s1=(sd*c1-cd*s1)+s1
439 c1=2.d0-(c2**2+s1**2)
440 s1=c1*s1
441 c1=c1*c2
442 c2=c1**2-s1**2
443 s2=2.d0*c1*s1
444 c3=c2*c1-s2*s1
445 s3=c2*s1+s2*c1
446 kk=kk-nt+jc
447 if(kk .le. kspan) go to 420
448 kk=kk-kspan+inc
449 if(kk .le. jc) go to 410
450 if(kspan .eq. jc) go to 800
451 go to 100
452 450 akp=akm+bjm
453 akm=akm-bjm
454 bkp=bkm-ajm
455 bkm=bkm+ajm
456 if(s1 .ne. 0) go to 430
457 460 a(k1)=akp
458 b(k1)=bkp
459 a(k2)=ajp
460 b(k2)=bjp
461 a(k3)=akm
462 b(k3)=bkm
463 kk=k3+kspan
464 if(kk .le. nt) go to 420
465 go to 440
466 ! transform for factor of 5 (optional code)
467 510 c2=c72**2-s72**2
468 s2=2.d0*c72*s72
469 520 k1=kk+kspan
470 k2=k1+kspan
471 k3=k2+kspan
472 k4=k3+kspan
473 akp=a(k1)+a(k4)
474 akm=a(k1)-a(k4)
475 bkp=b(k1)+b(k4)
476 bkm=b(k1)-b(k4)
477 ajp=a(k2)+a(k3)
478 ajm=a(k2)-a(k3)
479 bjp=b(k2)+b(k3)
480 bjm=b(k2)-b(k3)
481 aa=a(kk)
482 bb=b(kk)
483 a(kk)=aa+akp+ajp
484 b(kk)=bb+bkp+bjp
485 ak=akp*c72+ajp*c2+aa
486 bk=bkp*c72+bjp*c2+bb
487 aj=akm*s72+ajm*s2
488 bj=bkm*s72+bjm*s2
489 a(k1)=ak-bj
490 a(k4)=ak+bj
491 b(k1)=bk+aj
492 b(k4)=bk-aj
493 ak=akp*c2+ajp*c72+aa
494 bk=bkp*c2+bjp*c72+bb
495 aj=akm*s2-ajm*s72
496 bj=bkm*s2-bjm*s72
497 a(k2)=ak-bj
498 a(k3)=ak+bj
499 b(k2)=bk+aj
500 b(k3)=bk-aj
501 kk=k4+kspan
502 if(kk .lt. nn) go to 520
503 kk=kk-nn
504 if(kk .le. kspan) go to 520
505 go to 700
506 ! transform for odd factors
507 600 k=nfac(i)
508 kspnn=kspan
509 kspan=kspan/k
510 if(k .eq. 3) go to 320
511 if(k .eq. 5) go to 510
512 if(k .eq. jf) go to 640
513 jf=k
514 s1=rad/dble(k)
515 c1=dcos(s1)
516 s1=dsin(s1)
517 if(jf .gt. maxf) go to 998
518 ck(jf)=1.d0
519 sk(jf)=0.d0
520 j=1
521 630 ck(j)=ck(k)*c1+sk(k)*s1
522 sk(j)=ck(k)*s1-sk(k)*c1
523 k=k-1
524 ck(k)=ck(j)
525 sk(k)=-sk(j)
526 j=j+1
527 if(j .lt. k) go to 630
528 640 k1=kk
529 k2=kk+kspnn
530 aa=a(kk)
531 bb=b(kk)
532 ak=aa
533 bk=bb
534 j=1
535 k1=k1+kspan
536 650 k2=k2-kspan
537 j=j+1
538 at(j)=a(k1)+a(k2)
539 ak=at(j)+ak
540 bt(j)=b(k1)+b(k2)
541 bk=bt(j)+bk
542 j=j+1
543 at(j)=a(k1)-a(k2)
544 bt(j)=b(k1)-b(k2)
545 k1=k1+kspan
546 if(k1 .lt. k2) go to 650
547 a(kk)=ak
548 b(kk)=bk
549 k1=kk
550 k2=kk+kspnn
551 j=1
552 660 k1=k1+kspan
553 k2=k2-kspan
554 jj=j
555 ak=aa
556 bk=bb
557 aj=0.d0
558 bj=0.d0
559 k=1
560 670 k=k+1
561 ak=at(k)*ck(jj)+ak
562 bk=bt(k)*ck(jj)+bk
563 k=k+1
564 aj=at(k)*sk(jj)+aj
565 bj=bt(k)*sk(jj)+bj
566 jj=jj+j
567 if(jj .gt. jf) jj=jj-jf
568 if(k .lt. jf) go to 670
569 k=jf-j
570 a(k1)=ak-bj
571 b(k1)=bk+aj
572 a(k2)=ak+bj
573 b(k2)=bk-aj
574 j=j+1
575 if(j .lt. k) go to 660
576 kk=kk+kspnn
577 if(kk .le. nn) go to 640
578 kk=kk-nn
579 if(kk .le. kspan) go to 640
580 ! multiply by rotation factor (except for factors of 2 and 4)
581 700 if(i .eq. m) go to 800
582 kk=jc+1
583 710 c2=1.d0-cd
584 s1=sd
585 720 c1=c2
586 s2=s1
587 kk=kk+kspan
588 730 ak=a(kk)
589 a(kk)=c2*ak-s2*b(kk)
590 b(kk)=s2*ak+c2*b(kk)
591 kk=kk+kspnn
592 if(kk .le. nt) go to 730
593 ak=s1*s2
594 s2=s1*c2+c1*s2
595 c2=c1*c2-ak
596 kk=kk-nt+kspan
597 if(kk .le. kspnn) go to 730
598 c2=c1-(cd*c1+sd*s1)
599 s1=s1+(sd*c1-cd*s1)
600 c1=2.d0-(c2**2+s1**2)
601 s1=c1*s1
602 c2=c1*c2
603 kk=kk-kspnn+jc
604 if(kk .le. kspan) go to 720
605 kk=kk-kspan+jc+inc
606 if(kk .le. jc+jc) go to 710
607 go to 100
608 ! permute the results to normal order---done in two stages
609 ! permutation for square factors of n
610 800 np(1)=ks
611 if(kt .eq. 0) go to 890
612 k=kt+kt+1
613 if(m .lt. k) k=k-1
614 j=1
615 np(k+1)=jc
616 810 np(j+1)=np(j)/nfac(j)
617 np(k)=np(k+1)*nfac(j)
618 j=j+1
619 k=k-1
620 if(j .lt. k) go to 810
621 k3=np(k+1)
622 kspan=np(2)
623 kk=jc+1
624 k2=kspan+1
625 j=1
626 if(n .ne. ntot) go to 850
627 ! permutation for single-variate transform (optional code)
628 820 ak=a(kk)
629 a(kk)=a(k2)
630 a(k2)=ak
631 bk=b(kk)
632 b(kk)=b(k2)
633 b(k2)=bk
634 kk=kk+inc
635 k2=kspan+k2
636 if(k2 .lt. ks) go to 820
637 830 k2=k2-np(j)
638 j=j+1
639 k2=np(j+1)+k2
640 if(k2 .gt. np(j)) go to 830
641 j=1
642 840 if(kk .lt. k2) go to 820
643 kk=kk+inc
644 k2=kspan+k2
645 if(k2 .lt. ks) go to 840
646 if(kk .lt. ks) go to 830
647 jc=k3
648 go to 890
649 ! permutation for multivariate transform
650 850 k=kk+jc
651 860 ak=a(kk)
652 a(kk)=a(k2)
653 a(k2)=ak
654 bk=b(kk)
655 b(kk)=b(k2)
656 b(k2)=bk
657 kk=kk+inc
658 k2=k2+inc
659 if(kk .lt. k) go to 860
660 kk=kk+ks-jc
661 k2=k2+ks-jc
662 if(kk .lt. nt) go to 850
663 k2=k2-nt+kspan
664 kk=kk-nt+jc
665 if(k2 .lt. ks) go to 850
666 870 k2=k2-np(j)
667 j=j+1
668 k2=np(j+1)+k2
669 if(k2 .gt. np(j)) go to 870
670 j=1
671 880 if(kk .lt. k2) go to 850
672 kk=kk+jc
673 k2=kspan+k2
674 if(k2 .lt. ks) go to 880
675 if(kk .lt. ks) go to 870
676 jc=k3
677 890 if(2*kt+1 .ge. m) return
678 kspnn=np(kt+1)
679 ! permutation for square-free factors of n
680 j=m-kt
681 nfac(j+1)=1
682 900 nfac(j)=nfac(j)*nfac(j+1)
683 j=j-1
684 if(j .ne. kt) go to 900
685 kt=kt+1
686 nn=nfac(kt)-1
687 if(nn .gt. maxp) go to 998
688 jj=0
689 j=0
690 go to 906
691 902 jj=jj-k2
692 k2=kk
693 k=k+1
694 kk=nfac(k)
695 904 jj=kk+jj
696 if(jj .ge. k2) go to 902
697 np(j)=jj
698 906 k2=nfac(kt)
699 k=kt+1
700 kk=nfac(k)
701 j=j+1
702 if(j .le. nn) go to 904
703 ! determine the permutation cycles of length greater than 1
704 j=0
705 go to 914
706 910 k=kk
707 kk=np(k)
708 np(k)=-kk
709 if(kk .ne. j) go to 910
710 k3=kk
711 914 j=j+1
712 kk=np(j)
713 if(kk .lt. 0) go to 914
714 if(kk .ne. j) go to 910
715 np(j)=-j
716 if(j .ne. nn) go to 914
717 maxf=inc*maxf
718 ! reorder a and b, following the permutation cycles
719 go to 950
720 924 j=j-1
721 if(np(j) .lt. 0) go to 924
722 jj=jc
723 926 kspan=jj
724 if(jj .gt. maxf) kspan=maxf
725 jj=jj-kspan
726 k=np(j)
727 kk=jc*k+ii+jj
728 k1=kk+kspan
729 k2=0
730 928 k2=k2+1
731 at(k2)=a(k1)
732 bt(k2)=b(k1)
733 k1=k1-inc
734 if(k1 .ne. kk) go to 928
735 932 k1=kk+kspan
736 k2=k1-jc*(k+np(k))
737 k=-np(k)
738 936 a(k1)=a(k2)
739 b(k1)=b(k2)
740 k1=k1-inc
741 k2=k2-inc
742 if(k1 .ne. kk) go to 936
743 kk=k2
744 if(k .ne. j) go to 932
745 k1=kk+kspan
746 k2=0
747 940 k2=k2+1
748 a(k1)=at(k2)
749 b(k1)=bt(k2)
750 k1=k1-inc
751 if(k1 .ne. kk) go to 940
752 if(jj .ne. 0) go to 926
753 if(j .ne. 1) go to 924
754 950 j=k3+1
755 nt=nt-kspnn
756 ii=nt-inc+1
757 if(nt .ge. 0) go to 924
758 return
759 ! error finish, insufficient array storage
760 998 isn=0
761 print 999
762 stop
763 999 format(44h0array bounds exceeded within subroutine fft)
764 end subroutine fft_raw
765
766end module mod_fft
Self-contained complex FFT utilities based on the mixed-radix Singleton transform historically embedd...
Definition mod_fft.t:3
subroutine, public fft_2d_real_imag(ar, ai, inverse)
In-place two-dimensional FFT on split real/imaginary storage. This avoids allocation and copying in r...
Definition mod_fft.t:181
subroutine, public fft_raw(a, b, ntot, n, nspan, isn)
Definition mod_fft.t:206
subroutine, public fft_2d(data, inverse)
In-place complex two-dimensional FFT. The inverse is normalized.
Definition mod_fft.t:152
character(len=128) function, public fft_factorization(n)
Human-readable prime factorization used in unsupported-size diagnostics.
Definition mod_fft.t:83
integer function, public fft_next_supported(n)
Definition mod_fft.t:73
logical function, public fft_size_supported(n)
Return whether the legacy mixed-radix workspace can handle a transform.
Definition mod_fft.t:19
subroutine, public fft_1d(data, inverse)
In-place complex one-dimensional FFT. The inverse is normalized.
Definition mod_fft.t:129