245
245
# needed to determine whether it is applicable. We need to put
246
246
# this into a type to support a finalizer on the fftw_plan.
247
247
# K is FORWARD/BACKWARD for forward/backward or r2c/c2r plans, respectively.
248
- # For r2r plans, K is a tuple of the transform kinds along each dimension.
248
+ # For r2r plans, the field kinds:: K is a tuple/vector of the transform kinds along each dimension.
249
249
abstract type FFTWPlan{T<: fftwNumber ,K,inplace} <: Plan{T} end
250
- for P in (:cFFTWPlan , :rFFTWPlan , :r2rFFTWPlan ) # complex, r2c/c2r, and r2r
250
+ for P in (:cFFTWPlan , :rFFTWPlan ) # complex, r2c/c2r
251
251
@eval begin
252
252
mutable struct $ P{T<: fftwNumber ,K,inplace,N,G} <: FFTWPlan{T,K,inplace}
253
253
plan:: PlanPtr
@@ -277,6 +277,34 @@ for P in (:cFFTWPlan, :rFFTWPlan, :r2rFFTWPlan) # complex, r2c/c2r, and r2r
277
277
end
278
278
end
279
279
280
+ mutable struct r2rFFTWPlan{T<: fftwNumber ,K,inplace,N,G} <: FFTWPlan{T,K,inplace}
281
+ plan:: PlanPtr
282
+ sz:: NTuple{N,Int} # size of array on which plan operates (Int tuple)
283
+ osz:: NTuple{N,Int} # size of output array (Int tuple)
284
+ istride:: NTuple{N,Int} # strides of input
285
+ ostride:: NTuple{N,Int} # strides of output
286
+ ialign:: Int32 # alignment mod 16 of input
287
+ oalign:: Int32 # alignment mod 16 of input
288
+ flags:: UInt32 # planner flags
289
+ region:: G # region (iterable) of dims that are transformed
290
+ kinds:: K
291
+ pinv:: ScaledPlan
292
+ function r2rFFTWPlan {T,K,inplace,N,G} (plan:: PlanPtr , flags:: Integer , R:: G ,
293
+ X:: StridedArray{T,N} ,
294
+ Y:: StridedArray , kinds:: K ) where {T<: fftwNumber ,K,inplace,N,G}
295
+ p = new (plan, size (X), size (Y), strides (X), strides (Y),
296
+ alignment_of (X), alignment_of (Y), flags, R, kinds)
297
+ finalizer (maybe_destroy_plan, p)
298
+ p
299
+ end
300
+ end
301
+
302
+ function r2rFFTWPlan {T,K,inplace,N} (plan:: PlanPtr , flags:: Integer , R:: G ,
303
+ X:: StridedArray{T,N} ,
304
+ Y:: StridedArray , kinds:: K ) where {T<: fftwNumber ,K,inplace,N,G}
305
+ r2rFFTWPlan {T,K,inplace,N,G} (plan, flags, R, X, Y, kinds)
306
+ end
307
+
280
308
size (p:: FFTWPlan ) = p. sz
281
309
282
310
unsafe_convert (:: Type{PlanPtr} , p:: FFTWPlan ) = p. plan
@@ -427,16 +455,17 @@ function show(io::IO, p::rFFTWPlan{T,K,inplace}) where {T,K,inplace}
427
455
end
428
456
429
457
function show (io:: IO , p:: r2rFFTWPlan{T,K,inplace} ) where {T,K,inplace}
458
+ kinds = p. kinds
430
459
print (io, inplace ? " FFTW in-place r2r " : " FFTW r2r " )
431
- if isempty (K )
460
+ if isempty (kinds )
432
461
print (io, " 0-dimensional" )
433
- elseif K == ntuple (i -> K [1 ], length (K ))
434
- print (io, kind2string (K [1 ]))
435
- if length (K ) > 1
436
- print (io, " ^" , length (K ))
462
+ elseif kinds == ntuple (i -> kinds [1 ], length (kinds ))
463
+ print (io, kind2string (kinds [1 ]))
464
+ if length (kinds ) > 1
465
+ print (io, " ^" , length (kinds ))
437
466
end
438
467
else
439
- print (io, join (map (kind2string, K ), " ×" ))
468
+ print (io, join (map (kind2string, kinds ), " ×" ))
440
469
end
441
470
print (io, " plan for " )
442
471
showfftdims (io, p. sz, p. istride, T)
@@ -553,7 +582,6 @@ function dims_howmany(X::StridedArray, Y::StridedArray,
553
582
return (dims, howmany)
554
583
end
555
584
556
- # check & convert kinds into int32 array with same length as region
557
585
function fix_kinds (region, kinds)
558
586
if length (kinds) != length (region)
559
587
if length (kinds) > length (region)
@@ -575,9 +603,14 @@ function fix_kinds(region, kinds)
575
603
end
576
604
return k
577
605
end
606
+ fix_kinds (region:: Tuple , kinds:: Integer ) = ntuple (_-> Int32 (kinds), length (region))
607
+ fix_kinds (region:: Tuple , kinds:: Tuple{Integer} ) = fix_kinds (region, kinds[1 ])
578
608
579
- # low-level FFTWPlan creation (for internal use in FFTW module)
609
+ # Potentially avoid an extra `collect`
610
+ _collect (T, x) = collect (T, x)
611
+ _collect (:: Type{T} , x:: AbstractVector ) where {T} = convert (Vector{T}, x)
580
612
613
+ # low-level FFTWPlan creation (for internal use in FFTW module)
581
614
for (Tr,Tc,fftw,lib) in ((:Float64 ,:(Complex{Float64})," fftw" ,:libfftw3 ),
582
615
(:Float32 ,:(Complex{Float32})," fftwf" ,:libfftw3f ))
583
616
@eval @exclusive function cFFTWPlan {$Tc,K,inplace,N} (X:: StridedArray{$Tc,N} ,
@@ -644,6 +677,7 @@ for (Tr,Tc,fftw,lib) in ((:Float64,:(Complex{Float64}),"fftw",:libfftw3),
644
677
Y:: StridedArray{$Tr,N} ,
645
678
region, kinds, flags:: Integer ,
646
679
timelimit:: Real ) where {inplace,N}
680
+
647
681
R = isa (region, Tuple) ? region : copy (region)
648
682
knd = fix_kinds (region, kinds)
649
683
unsafe_set_timelimit ($ Tr, timelimit)
@@ -653,19 +687,20 @@ for (Tr,Tc,fftw,lib) in ((:Float64,:(Complex{Float64}),"fftw",:libfftw3),
653
687
(Int32, Ptr{Int}, Int32, Ptr{Int},
654
688
Ptr{$ Tr}, Ptr{$ Tr}, Ptr{Int32}, UInt32),
655
689
size (dims,2 ), dims, size (howmany,2 ), howmany,
656
- X, Y, knd, flags)
690
+ X, Y, _collect (Int32, knd) , flags)
657
691
unsafe_set_timelimit ($ Tr, NO_TIMELIMIT)
658
692
if plan == C_NULL
659
693
error (" FFTW could not create plan" ) # shouldn't normally happen
660
694
end
661
- r2rFFTWPlan {$Tr,(map(Int, knd)...,), inplace,N} (plan, flags, R, X, Y)
695
+ r2rFFTWPlan {$Tr,typeof( knd), inplace,N} (plan, flags, R, X, Y, knd )
662
696
end
663
697
664
698
# support r2r transforms of complex = transforms of real & imag parts
665
699
@eval @exclusive function r2rFFTWPlan {$Tc,Any,inplace,N} (X:: StridedArray{$Tc,N} ,
666
700
Y:: StridedArray{$Tc,N} ,
667
701
region, kinds, flags:: Integer ,
668
702
timelimit:: Real ) where {inplace,N}
703
+
669
704
R = isa (region, Tuple) ? region : copy (region)
670
705
knd = fix_kinds (region, kinds)
671
706
unsafe_set_timelimit ($ Tr, timelimit)
@@ -678,14 +713,13 @@ for (Tr,Tc,fftw,lib) in ((:Float64,:(Complex{Float64}),"fftw",:libfftw3),
678
713
(Int32, Ptr{Int}, Int32, Ptr{Int},
679
714
Ptr{$ Tc}, Ptr{$ Tc}, Ptr{Int32}, UInt32),
680
715
size (dims,2 ), dims, size (howmany,2 ), howmany,
681
- X, Y, knd, flags)
716
+ X, Y, _collect (Int32, knd) , flags)
682
717
unsafe_set_timelimit ($ Tr, NO_TIMELIMIT)
683
718
if plan == C_NULL
684
719
error (" FFTW could not create plan" ) # shouldn't normally happen
685
720
end
686
- r2rFFTWPlan {$Tc,(map(Int, knd)...,), inplace,N} (plan, flags, R, X, Y)
721
+ r2rFFTWPlan {$Tc,typeof( knd), inplace,N} (plan, flags, R, X, Y, knd )
687
722
end
688
-
689
723
end
690
724
691
725
# Convert arrays of numeric types to FFTW-supported packed complex-float types
@@ -888,15 +922,16 @@ end
888
922
889
923
# FFTW r2r transforms (low-level interface)
890
924
925
+ _ntupleid (v) = ntuple (identity, v)
891
926
for f in (:r2r , :r2r! )
892
927
pf = Symbol (" plan_" , f)
893
928
@eval begin
894
929
$ f (x:: AbstractArray{<:fftwNumber} , kinds) = $ pf (x, kinds) * x
895
930
$ f (x:: AbstractArray{<:fftwNumber} , kinds, region) = $ pf (x, kinds, region) * x
896
- $ pf (x:: AbstractArray , kinds; kws... ) = $ pf (x, kinds, 1 : ndims (x); kws... )
897
- $ f (x:: AbstractArray{<:Real} , kinds, region= 1 : ndims (x)) = $ f (fftwfloat (x), kinds, region)
931
+ $ pf (x:: AbstractArray , kinds; kws... ) = $ pf (x, kinds, _ntupleid ( Val ( ndims (x)) ); kws... )
932
+ $ f (x:: AbstractArray{<:Real} , kinds, region= _ntupleid ( Val ( ndims (x)) )) = $ f (fftwfloat (x), kinds, region)
898
933
$ pf (x:: AbstractArray{<:Real} , kinds, region; kws... ) = $ pf (fftwfloat (x), kinds, region; kws... )
899
- $ f (x:: AbstractArray{<:Complex} , kinds, region= 1 : ndims (x)) = $ f (fftwcomplex (x), kinds, region)
934
+ $ f (x:: AbstractArray{<:Complex} , kinds, region= _ntupleid ( Val ( ndims (x)) )) = $ f (fftwcomplex (x), kinds, region)
900
935
$ pf (x:: AbstractArray{<:Complex} , kinds, region; kws... ) = $ pf (fftwcomplex (x), kinds, region; kws... )
901
936
end
902
937
end
@@ -955,13 +990,14 @@ function plan_inv(p::r2rFFTWPlan{T,K,inplace,N};
955
990
return plan
956
991
end
957
992
X = Array {T} (undef, p. sz)
958
- iK = fix_kinds (p. region, [inv_kind[k] for k in K])
993
+ # broadcast getindex to preserve tuples
994
+ iK = fix_kinds (p. region, getindex .((inv_kind,), p. kinds))
959
995
Y = inplace ? X : fakesimilar (p. flags, X, T)
960
996
ScaledPlan (r2rFFTWPlan {T,Any,inplace,N} (X, Y, p. region, iK,
961
997
p. flags, NO_TIMELIMIT),
962
998
normalization (real (T),
963
999
map (logical_size, [p. sz... ][[p. region... ]], iK),
964
- 1 : length (iK )))
1000
+ 1 : length (p . region )))
965
1001
end
966
1002
967
1003
function mul! (y:: StridedArray{T} , p:: r2rFFTWPlan{T} , x:: StridedArray{T} ) where T
0 commit comments