1 #ifndef DOXYGEN_SHOULD_SKIP_THIS 
   28 #include "sll_working_precision.h" 
   29 #include "sll_assert.h" 
   30 #include "sll_memory.h" 
   31 #include "sll_errors.h" 
   83       sll_comp64, 
allocatable, 
private :: t(:)
 
   85       sll_real64, 
allocatable, 
private :: twiddles(:)
 
   87       sll_real64, 
allocatable, 
private :: twiddles_n(:)
 
   90       sll_int32                        :: direction
 
   91       sll_int32                        :: problem_rank
 
   92       sll_int32, 
allocatable           :: problem_shape(:)
 
   93       sll_int32, 
allocatable, 
private  :: scramble_index(:)
 
   94       sll_int32, 
private               :: transform_type 
 
   98    integer, 
parameter :: sll_p_fft_forward = -1
 
  100    integer, 
parameter :: sll_p_fft_backward = 1
 
  103    integer, 
parameter :: sll_p_fft_measure = -1
 
  104    integer, 
parameter :: sll_p_fft_patient = -1
 
  105    integer, 
parameter :: sll_p_fft_estimate = -1
 
  106    integer, 
parameter :: sll_p_fft_exhaustive = -1
 
  107    integer, 
parameter :: sll_p_fft_wisdom_only = -1 
 
  110    integer, 
parameter :: p_fftw_c2c_1d = 0
 
  111    integer, 
parameter :: p_fftw_r2r_1d = 1
 
  112    integer, 
parameter :: p_fftw_r2c_1d = 2
 
  113    integer, 
parameter :: p_fftw_c2r_1d = 3
 
  114    integer, 
parameter :: p_fftw_c2c_2d = 4
 
  115    integer, 
parameter :: p_fftw_r2r_2d = 5
 
  116    integer, 
parameter :: p_fftw_r2c_2d = 6
 
  117    integer, 
parameter :: p_fftw_c2r_2d = 7
 
  123       print *, 
'The library used is SLLFFT' 
  128       sll_int32, 
intent(in)  :: n                
 
  129       complex(f64), 
pointer     :: data(:)
 
  132       sll_warning(
'sll_f_fft_allocate_aligned_complex', 
'Aligned allocation not implemented for SLLFFT. Usual allocation.')
 
  138       sll_int32, 
intent(in)  :: n                
 
  139       real(f64), 
pointer                :: data(:)
 
  142       sll_warning(
'sll_f_fft_allocate_aligned_real', 
'Aligned allocation not implemented for SLLFFT. Usual allocation.')
 
  150       complex(f64), 
pointer :: data(:)
 
  153       sll_warning(
'sll_s_fft_deallocate_aligned_complex', 
'Aligned deallocation not implemented for SLLFFT. Usual deallocation.')
 
  161       real(f64), 
pointer :: data(:)
 
  164       sll_warning(
'sll_s_fft_deallocate_aligned_real', 
'Aligned deallocation not implemented for SLLFFT. Usual deallocation.')
 
  173       type(sll_t_fft), 
intent(in) :: plan
 
  174       sll_int32, 
intent(out) :: k_list(0:) 
 
  178       n = plan%problem_shape(1)
 
  180       if (
size(k_list) /= n) 
then 
  181          sll_error(
"sll_s_fft_get_k_list_c2c_1d", 
"k_list must have n elements")
 
  184       k_list(0:n/2) = [(k, k=0, n/2)]
 
  185       k_list(n/2 + 1:n - 1) = [(k - n, k=n/2 + 1, n - 1)]
 
  194       type(sll_t_fft), 
intent(in) :: plan
 
  195       sll_int32, 
intent(out) :: k_list(0:) 
 
  199       n = plan%problem_shape(1)
 
  201       if (
size(k_list) /= n) 
then 
  202          sll_error(
"sll_s_fft_get_k_list_r2r_1d", 
"k_list must have n elements")
 
  205       k_list(0:n/2) = [(k, k=0, n/2)]
 
  206       k_list(n/2 + 1:n - 1) = [(n - k, k=n/2 + 1, n - 1)]
 
  215       type(sll_t_fft), 
intent(in) :: plan
 
  216       sll_int32, 
intent(out) :: k_list(0:) 
 
  220       n_2 = plan%problem_shape(1)/2
 
  222       if (
size(k_list) /= n_2 + 1) 
then 
  223          sll_error(
"sll_s_fft_get_k_list_r2c_1d", 
"k_list must have n/2+1 elements")
 
  226       k_list(:) = [(k, k=0, n_2)]
 
  234       type(sll_t_fft), 
intent(in) :: plan
 
  235       sll_real64, 
intent(in) :: 
data(0:) 
 
  236       sll_int32, 
intent(in) :: k        
 
  240       n = plan%problem_shape(1)
 
  242       if (k == 0) then; ck = cmplx(
data(k), 0.0_f64, kind=f64)
 
  243       else if (k <= (n + 1)/2 - 1) then; ck = cmplx(
data(k), 
data(n - k), kind=f64)
 
  244       else if (k == n/2) then; ck = cmplx(
data(k), 0.0_f64, kind=f64)
 
  245       else if (k <= n - 1) then; ck = cmplx(
data(n - k), -
data(k), kind=f64)
 
  247          sll_error(
"sll_f_fft_get_mode_r2c_1d", 
"k must be between 0 and n-1")
 
  256       type(sll_t_fft), 
intent(in) :: plan
 
  257       sll_real64, 
intent(inout) :: 
data(0:)  
 
  258       sll_comp64, 
intent(in) :: ck        
 
  259       sll_int32, 
intent(in) :: k         
 
  262       n = plan%problem_shape(1)
 
  264       if (k == 0) then; 
data(0) = real(ck) 
 
  265       else if (k <= (n + 1)/2 - 1) then; 
data(k) = real(ck); 
data(n - k) = aimag(ck)
 
  266       else if (k == n/2) then; 
data(k) = real(ck) 
 
  267       else if (k <= n - 1) then; 
data(n - k) = real(ck); 
data(k) = -aimag(ck)
 
  269          sll_error(
"sll_s_fft_set_mode_c2r_1d", 
"k must be between 0 and n-1")
 
  326    subroutine sll_s_fft_init_c2c_1d(plan, nx, array_in, array_out, direction, normalized, aligned, optimization)
 
  327       type(sll_t_fft), 
intent(out)        :: plan
 
  328       sll_int32, 
intent(in)         :: nx 
 
  329       sll_comp64, 
intent(inout)      :: array_in(:) 
 
  330       sll_comp64, 
intent(inout)      :: array_out(:) 
 
  331       sll_int32, 
intent(in)         :: direction  
 
  332       logical, 
optional, 
intent(in)         :: normalized
 
  333       logical, 
optional, 
intent(in)         :: aligned
 
  334       sll_int32, 
optional, 
intent(in)         :: optimization 
 
  339       sll_assert(
size(array_in) .ge. nx)
 
  340       sll_assert(
size(array_out) .ge. nx)
 
  341       plan%transform_type = p_fftw_c2c_1d
 
  342       plan%direction = direction
 
  343       if (
present(normalized)) 
then 
  344          plan%normalized = normalized
 
  346          plan%normalized = .false.
 
  349       plan%problem_rank = 1
 
  350       sll_allocate(plan%problem_shape(1), ierr)
 
  351       plan%problem_shape = (/nx/)
 
  353       sll_allocate(plan%scramble_index(0:nx - 1), ierr)
 
  357          plan%scramble_index(i) = i
 
  359       sll_allocate(plan%t(1:nx/2), ierr)
 
  360       call compute_twiddles(nx, plan%t)
 
  361       if (direction == sll_p_fft_forward) 
then 
  362          plan%t = conjg(plan%t)
 
  364       call bit_reverse_complex(nx/2, plan%t)
 
  369       type(sll_t_fft), 
intent(in)            :: plan
 
  370       sll_comp64, 
intent(inout)         :: array_in(:) 
 
  371       sll_comp64, 
intent(inout)         :: array_out(:) 
 
  375       sll_assert(plan%transform_type == p_fftw_c2c_1d)
 
  377       if (loc(array_in(1)) .ne. loc(array_out(1))) 
then  
  381       call fft_dit_nr(array_out, plan%problem_shape(1), plan%t, plan%direction)
 
  382       call bit_reverse_complex(plan%problem_shape(1), array_out)
 
  384       if (plan%normalized .EQV. .true.) 
then 
  385          factor = 1.0_f64/real(plan%problem_shape(1), kind=f64)
 
  386          array_out = factor*array_out
 
  395    subroutine sll_s_fft_init_c2c_2d(plan, nx, ny, array_in, array_out, direction, normalized, aligned, optimization)
 
  396       type(sll_t_fft), 
intent(out)    :: plan
 
  397       sll_int32, 
intent(in)     :: nx 
 
  398       sll_int32, 
intent(in)     :: ny 
 
  399       sll_comp64, 
intent(inout)  :: array_in(0:, 0:) 
 
  400       sll_comp64, 
intent(inout)  :: array_out(0:, 0:) 
 
  401       sll_int32, 
intent(in)     :: direction  
 
  402       logical, 
optional, 
intent(in)     :: normalized
 
  403       logical, 
optional, 
intent(in)     :: aligned
 
  404       sll_int32, 
optional, 
intent(in)      :: optimization 
 
  409       sll_assert(
size(array_in, dim=1) .ge. nx)
 
  410       sll_assert(
size(array_in, dim=2) .ge. ny)
 
  411       sll_assert(
size(array_out, dim=1) .ge. nx)
 
  412       sll_assert(
size(array_out, dim=2) .ge. ny)
 
  416       plan%transform_type = p_fftw_c2c_2d
 
  417       plan%direction = direction
 
  418       if (
present(normalized)) 
then 
  419          plan%normalized = normalized
 
  421          plan%normalized = .false.
 
  424       plan%problem_rank = 2
 
  425       sll_allocate(plan%problem_shape(2), ierr)
 
  426       plan%problem_shape = (/nx, ny/)
 
  428       sll_allocate(plan%t(1:nx/2 + ny/2), ierr)
 
  430       call compute_twiddles(nx, plan%t(1:nx/2))
 
  431       if (direction == sll_p_fft_forward) 
then 
  432          plan%t(1:nx/2) = conjg(plan%t(1:nx/2))
 
  434       call bit_reverse_complex(nx/2, plan%t(1:nx/2))
 
  436       call compute_twiddles(ny, plan%t(nx/2 + 1:nx/2 + ny/2))
 
  437       if (direction == sll_p_fft_forward) 
then 
  438          plan%t(nx/2 + 1:nx/2 + ny/2) = conjg(plan%t(nx/2 + 1:nx/2 + ny/2))
 
  440       call bit_reverse_complex(ny/2, plan%t(nx/2 + 1:nx/2 + ny/2))
 
  446       type(sll_t_fft), 
intent(in)     :: plan
 
  447       sll_comp64, 
intent(inout)  :: array_in(0:, 0:) 
 
  448       sll_comp64, 
intent(inout)  :: array_out(0:, 0:) 
 
  450       sll_int32                                       :: i, nx, ny
 
  451       sll_int32, 
dimension(2)                         :: fft_shape
 
  454       sll_assert(plan%transform_type == p_fftw_c2c_2d)
 
  456       if (loc(array_in(1, 1)) .ne. loc(array_out(1, 1))) 
then  
  459       fft_shape(1:2) = plan%problem_shape(1:2)
 
  464          call fft_dit_nr(array_out(0:nx - 1, i), nx, plan%t(1:nx/2), plan%direction)
 
  465          call bit_reverse_complex(nx, array_out(0:nx - 1, i))
 
  470             array_out(i, 0:ny - 1), &
 
  472             plan%t(nx/2 + 1:nx/2 + ny/2), &
 
  474          call bit_reverse_complex(ny, array_out(i, 0:ny - 1))
 
  477       if (plan%normalized .EQV. .true.) 
then 
  478          factor = 1.0_f64/real(nx*ny, kind=f64)
 
  479          array_out = factor*array_out
 
  486    subroutine sll_s_fft_init_r2r_1d(plan, nx, array_in, array_out, direction, normalized, aligned, optimization)
 
  487       type(sll_t_fft), 
intent(out)   :: plan
 
  488       sll_int32, 
intent(in)    :: nx 
 
  489       sll_real64, 
intent(inout) :: array_in(:) 
 
  490       sll_real64, 
intent(inout) :: array_out(:) 
 
  491       sll_int32, 
intent(in)    :: direction  
 
  492       logical, 
optional, 
intent(in)    :: normalized
 
  493       logical, 
optional, 
intent(in)    :: aligned
 
  494       sll_int32, 
optional, 
intent(in)    :: optimization 
 
  498       sll_assert(
size(array_in) .eq. nx)
 
  499       sll_assert(
size(array_out) .eq. nx)
 
  500       plan%transform_type = p_fftw_r2r_1d
 
  501       plan%direction = direction
 
  502       if (
present(normalized)) 
then 
  503          plan%normalized = normalized
 
  505          plan%normalized = .false.
 
  508       plan%problem_rank = 1
 
  509       sll_allocate(plan%problem_shape(1), ierr)
 
  510       plan%problem_shape = (/nx/)
 
  512       sll_allocate(plan%scramble_index(0:nx/2), ierr)
 
  516       plan%scramble_index(0) = 0
 
  517       plan%scramble_index(1) = nx/2
 
  519          plan%scramble_index(i + 1) = i
 
  522       sll_allocate(plan%twiddles(0:nx/2 - 1), ierr)
 
  523       sll_allocate(plan%twiddles_n(0:nx - 1), ierr)
 
  524       call compute_twiddles_real_array(nx, plan%twiddles_n)
 
  525       call compute_twiddles_real_array(nx/2, plan%twiddles(0:nx/2 - 1))
 
  526       if (direction .eq. sll_p_fft_forward) 
then 
  527          call conjg_in_pairs(nx/2, plan%twiddles)
 
  529       call bit_reverse_in_pairs(nx/4, plan%twiddles(0:nx/2 - 1))
 
  534       type(sll_t_fft), 
intent(in)    :: plan
 
  535       sll_real64, 
intent(inout) :: array_in(:) 
 
  536       sll_real64, 
intent(inout) :: array_out(:) 
 
  540       sll_real64 :: tmp(plan%problem_shape(1))
 
  542       sll_assert(plan%transform_type == p_fftw_r2r_1d)
 
  544       nx = plan%problem_shape(1)
 
  546       if (loc(array_in(1)) .ne. loc(array_out(1))) 
then  
  551       if (plan%direction .EQ. sll_p_fft_backward) 
then 
  554             array_out(2*k + 1) = tmp(k + 1)
 
  555             array_out(2*k + 2) = tmp(nx - k + 1)
 
  557          array_out(1) = tmp(1)
 
  558          array_out(2) = tmp(nx/2 + 1)
 
  561       call real_data_fft_dit(array_out, nx, plan%twiddles, plan%twiddles_n, plan%direction)
 
  564       if (plan%direction .EQ. sll_p_fft_forward) 
then 
  567             array_out(k + 1) = tmp(2*k + 1)
 
  568             array_out(nx - k + 1) = tmp(2*k + 1 + 1)
 
  570          array_out(nx/2 + 1) = tmp(2)
 
  573       if (plan%normalized .EQV. .true.) 
then 
  574          factor = 1.0_f64/real(plan%problem_shape(1), kind=f64)
 
  575          array_out = factor*array_out
 
  584       type(sll_t_fft), 
intent(out)   :: plan
 
  585       sll_int32, 
intent(in)    :: nx 
 
  586       sll_real64, 
intent(inout) :: array_in(:) 
 
  587       sll_comp64, 
intent(out)   :: array_out(:) 
 
  588       logical, 
optional, 
intent(in)    :: normalized
 
  589       logical, 
optional, 
intent(in)    :: aligned
 
  590       sll_int32, 
optional, 
intent(in)    :: optimization 
 
  594       sll_assert(
size(array_in) .eq. nx)
 
  595       sll_assert(
size(array_out) .eq. nx/2 + 1)
 
  596       plan%transform_type = p_fftw_r2c_1d
 
  597       plan%direction = sll_p_fft_forward
 
  598       if (
present(normalized)) 
then 
  599          plan%normalized = normalized
 
  601          plan%normalized = .false.
 
  603       plan%problem_rank = 1
 
  604       sll_allocate(plan%problem_shape(1), ierr)
 
  605       plan%problem_shape = (/nx/)
 
  607       sll_allocate(plan%twiddles(0:nx/2 - 1), ierr)
 
  608       sll_allocate(plan%twiddles_n(0:nx - 1), ierr)
 
  609       call compute_twiddles_real_array(nx, plan%twiddles_n)
 
  610       call compute_twiddles_real_array(nx/2, plan%twiddles(0:nx/2 - 1))
 
  611       call conjg_in_pairs(nx/2, plan%twiddles)
 
  612       call bit_reverse_in_pairs(nx/4, plan%twiddles(0:nx/2 - 1))
 
  617       type(sll_t_fft), 
intent(in)            :: plan
 
  618       sll_real64, 
intent(inout)         :: array_in(0:) 
 
  619       sll_comp64, 
intent(out)           :: array_out(0:) 
 
  624       sll_assert(plan%transform_type == p_fftw_r2c_1d)
 
  626       nx = plan%problem_shape(1)
 
  628       call real_data_fft_dit(array_in, nx, plan%twiddles, plan%twiddles_n, plan%direction)
 
  630       array_out(0) = cmplx(array_in(0), 0.0_f64, kind=f64)
 
  632       array_out(nx/2) = cmplx(array_in(1), 0.0_f64, kind=f64)
 
  635          array_out(i) = cmplx(array_in(2*i), array_in(2*i + 1), kind=f64)
 
  639       if (plan%normalized .EQV. .true.) 
then 
  640          factor = 1.0_f64/real(plan%problem_shape(1), kind=f64)
 
  641          array_out = factor*array_out
 
  649       type(sll_t_fft), 
intent(out)      :: plan
 
  650       sll_int32, 
intent(in)       :: nx 
 
  651       sll_comp64, 
intent(in)       :: array_in(:)  
 
  652       sll_real64, 
intent(out)      :: array_out(:) 
 
  653       logical, 
optional, 
intent(in)       :: normalized
 
  654       logical, 
optional, 
intent(in)       :: aligned
 
  655       sll_int32, 
optional, 
intent(in)       :: optimization 
 
  659       sll_assert(
size(array_in) .eq. nx/2 + 1)
 
  660       sll_assert(
size(array_out) .eq. nx)
 
  661       plan%transform_type = p_fftw_c2r_1d
 
  662       plan%direction = sll_p_fft_backward
 
  663       if (
present(normalized)) 
then 
  664          plan%normalized = normalized
 
  666          plan%normalized = .false.
 
  668       plan%problem_rank = 1
 
  669       sll_allocate(plan%problem_shape(1), ierr)
 
  670       plan%problem_shape = (/nx/)
 
  672       sll_allocate(plan%twiddles(0:nx/2 - 1), ierr)
 
  673       sll_allocate(plan%twiddles_n(0:nx - 1), ierr)
 
  674       call compute_twiddles_real_array(nx, plan%twiddles_n)
 
  675       call compute_twiddles_real_array(nx/2, plan%twiddles(0:nx/2 - 1))
 
  676       call bit_reverse_in_pairs(nx/4, plan%twiddles(0:nx/2 - 1))
 
  681       type(sll_t_fft), 
intent(in)    :: plan
 
  682       sll_comp64, 
intent(inout) :: array_in(0:) 
 
  683       sll_real64, 
intent(inout) :: array_out(0:) 
 
  688       sll_assert(plan%transform_type == p_fftw_c2r_1d)
 
  690       nx = plan%problem_shape(1)
 
  693       array_out(0) = real(array_in(0), kind=f64)
 
  695       array_out(1) = real(array_in(nx/2), kind=f64)
 
  698          array_out(2*i) = real(array_in(i), kind=f64)
 
  699          array_out(2*i + 1) = aimag(array_in(i))
 
  701       call real_data_fft_dit(array_out, nx, plan%twiddles, plan%twiddles_n, plan%direction)
 
  703       if (plan%normalized .EQV. .true.) 
then 
  704          factor = 1.0_f64/real(plan%problem_shape(1), kind=f64)
 
  705          array_out = factor*array_out
 
  713    subroutine sll_s_fft_init_r2c_2d(plan, nx, ny, array_in, array_out, normalized, aligned, optimization)
 
  714       type(sll_t_fft), 
intent(out)   :: plan
 
  715       sll_int32, 
intent(in)    :: nx 
 
  716       sll_int32, 
intent(in)    :: ny 
 
  717       sll_real64, 
intent(inout) :: array_in(:, :) 
 
  718       sll_comp64, 
intent(out)   :: array_out(:, :) 
 
  719       logical, 
optional, 
intent(in)    :: normalized
 
  720       logical, 
optional, 
intent(in)    :: aligned
 
  721       sll_int32, 
optional, 
intent(in)    :: optimization 
 
  725       sll_assert(
size(array_in, dim=1) .eq. nx)
 
  726       sll_assert(
size(array_in, dim=2) .eq. ny)
 
  727       sll_assert(
size(array_out, dim=1) .eq. nx/2 + 1)
 
  728       sll_assert(
size(array_out, dim=2) .eq. ny)
 
  729       plan%transform_type = p_fftw_r2c_2d
 
  730       plan%direction = sll_p_fft_forward
 
  731       if (
present(normalized)) 
then 
  732          plan%normalized = normalized
 
  734          plan%normalized = .false.
 
  736       plan%problem_rank = 2
 
  737       sll_allocate(plan%problem_shape(2), ierr)
 
  738       plan%problem_shape = (/nx, ny/)
 
  740       sll_allocate(plan%t(1:ny/2), ierr)
 
  741       call compute_twiddles(ny, plan%t)
 
  742       plan%t = conjg(plan%t)
 
  743       call bit_reverse_complex(ny/2, plan%t)
 
  745       sll_allocate(plan%twiddles(0:nx/2 - 1), ierr)
 
  746       sll_allocate(plan%twiddles_n(0:nx - 1), ierr)
 
  747       call compute_twiddles_real_array(nx, plan%twiddles_n)
 
  748       call compute_twiddles_real_array(nx/2, plan%twiddles(0:nx/2 - 1))
 
  749       call conjg_in_pairs(nx/2, plan%twiddles)
 
  750       call bit_reverse_in_pairs(nx/4, plan%twiddles(0:nx/2 - 1))
 
  755       type(sll_t_fft), 
intent(in)           :: plan
 
  756       sll_real64, 
intent(inout)        :: array_in(0:, 0:)  
 
  757       sll_comp64, 
intent(out)          :: array_out(0:, 0:) 
 
  759       sll_int32                                       :: nx, i, ny, k
 
  762       sll_assert(plan%transform_type == p_fftw_r2c_2d)
 
  764       nx = plan%problem_shape(1)
 
  765       ny = plan%problem_shape(2)
 
  768          call real_data_fft_dit(array_in(0:nx - 1, k), nx, plan%twiddles, plan%twiddles_n, plan%direction)
 
  769          array_out(0, k) = cmplx(array_in(0, k), 0.0_f64, kind=f64)
 
  770          array_out(nx/2, k) = cmplx(array_in(1, k), 0.0_f64, kind=f64)
 
  772             array_out(i, k) = cmplx(array_in(2*i, k), array_in(2*i + 1, k), kind=f64)
 
  776          call fft_dit_nr(array_out(k, 0:ny - 1), ny, plan%t, plan%direction)
 
  777          call bit_reverse_complex(ny, array_out(k, 0:ny - 1))
 
  780       if (plan%normalized .EQV. .true.) 
then 
  781          factor = 1.0_f64/real(nx*ny, kind=f64)
 
  782          array_out = factor*array_out
 
  789    subroutine sll_s_fft_init_c2r_2d(plan, nx, ny, array_in, array_out, normalized, aligned, optimization)
 
  790       type(sll_t_fft), 
intent(out)      :: plan
 
  791       sll_int32, 
intent(in)       :: nx 
 
  792       sll_int32, 
intent(in)      :: ny 
 
  793       sll_comp64, 
intent(in)       :: array_in(:, :)  
 
  794       sll_real64, 
intent(out)      :: array_out(:, :) 
 
  795       logical, 
optional, 
intent(in)       :: normalized
 
  796       logical, 
optional, 
intent(in)       :: aligned
 
  797       sll_int32, 
optional, 
intent(in)       :: optimization 
 
  801       sll_assert(
size(array_in, dim=1) .eq. nx/2 + 1)
 
  802       sll_assert(
size(array_in, dim=2) .eq. ny)
 
  803       sll_assert(
size(array_out, dim=1) .eq. nx)
 
  804       sll_assert(
size(array_out, dim=2) .eq. ny)
 
  806       plan%transform_type = p_fftw_c2r_2d
 
  807       plan%direction = sll_p_fft_backward
 
  808       if (
present(normalized)) 
then 
  809          plan%normalized = normalized
 
  811          plan%normalized = .false.
 
  813       plan%problem_rank = 2
 
  814       sll_allocate(plan%problem_shape(2), ierr)
 
  815       plan%problem_shape = (/nx, ny/)
 
  817       sll_allocate(plan%t(1:ny/2), ierr)
 
  818       call compute_twiddles(ny, plan%t)
 
  819       call bit_reverse_complex(ny/2, plan%t)
 
  821       sll_allocate(plan%twiddles(0:nx/2 - 1), ierr)
 
  822       sll_allocate(plan%twiddles_n(0:nx - 1), ierr)
 
  823       call compute_twiddles_real_array(nx, plan%twiddles_n)
 
  824       call compute_twiddles_real_array(nx/2, plan%twiddles(0:nx/2 - 1))
 
  825       call bit_reverse_in_pairs(nx/4, plan%twiddles(0:nx/2 - 1))
 
  830       type(sll_t_fft), 
intent(in)    :: plan
 
  831       sll_comp64, 
intent(inout) :: array_in(0:, 0:) 
 
  832       sll_real64, 
intent(inout) :: array_out(0:, 0:) 
 
  834       sll_int32                                       :: nx, i, ny, k, j
 
  837       sll_assert(plan%transform_type == p_fftw_c2r_2d)
 
  839       nx = plan%problem_shape(1)
 
  840       ny = plan%problem_shape(2)
 
  843          call fft_dit_nr(array_in(j, 0:ny - 1), ny, plan%t, plan%direction)
 
  844          call bit_reverse_complex(ny, array_in(j, 0:ny - 1))
 
  847          array_out(0, i) = real(array_in(0, i), kind=f64)
 
  848          array_out(1, i) = real(array_in(nx/2, i), kind=f64)
 
  850             array_out(2*k, i) = real(array_in(k, i), kind=f64)
 
  851             array_out(2*k + 1, i) = aimag(array_in(k, i))
 
  853          call real_data_fft_dit(array_out(0:nx - 1, i), nx, plan%twiddles, plan%twiddles_n, plan%direction)
 
  856       if (plan%normalized .EQV. .true.) 
then 
  857          factor = 1.0_f64/real(nx*ny, kind=f64)
 
  858          array_out = factor*array_out
 
  869       type(sll_t_fft), 
intent(inout) :: plan
 
  871       if (
allocated(plan%t)) 
then 
  874       if (
allocated(plan%twiddles)) 
then 
  875          deallocate (plan%twiddles)
 
  877       if (
allocated(plan%twiddles_n)) 
then 
  878          deallocate (plan%twiddles_n)
 
  880       if (
allocated(plan%problem_shape)) 
then 
  881          deallocate (plan%problem_shape)
 
  900    subroutine compute_twiddles(n, t)
 
  901       intrinsic                                 :: exp, real
 
  903       sll_comp64, 
dimension(1:n/2), 
intent(out) :: t
 
  906       if (n .eq. 0 .or. n .eq. 1) 
then 
  907          print *, 
"ERROR: Zero array size passed to compute_twiddle_factors()." 
  909       else if (
size(t) .lt. n/2) 
then 
  910          print *, 
"ERROR: compute_twiddles(), array is of insufficient size." 
  913          theta = 2.0_f64*
sll_p_pi/real(n, kind=f64)      
 
  921             t(k + 1) = exp((0.0_f64, 1.0_f64)*theta*cmplx(k, 0.0, kind=f64))
 
  924          t(n/4 + 1) = (0.0_f64, 1.0_f64)
 
  926    end subroutine compute_twiddles
 
  932 #define CREAL0(array, i) array(2*(i)) 
  933 #define CIMAG0(array, i) array(2*(i)+1) 
  935 #define CREAL1(array, i) array(2*(i)-1) 
  936 #define CIMAG1(array, i) array(2*(i)) 
  940    subroutine compute_twiddles_real_array(n, t)
 
  941       intrinsic                                 :: cos, sin, real
 
  943       sll_real64, 
dimension(0:n - 1), 
intent(out) :: t
 
  947       theta = 2.0_f64*
sll_p_pi/real(n, kind=f64)      
 
  955          creal0(t, k) = cos(real(k, kind=f64)*theta)
 
  956          cimag0(t, k) = sin(real(k, kind=f64)*theta)
 
  959       creal0(t, 0) = 1.0_f64
 
  960       cimag0(t, 0) = 0.0_f64
 
  963          creal0(t, n/4) = 0.0_f64
 
  964          cimag0(t, n/4) = 1.0_f64
 
  968          creal0(t, n/8) = sqrt(2.0_f64)/2.0_f64
 
  969          cimag0(t, n/8) = sqrt(2.0_f64)/2.0_f64
 
  971    end subroutine compute_twiddles_real_array
 
  981 #define MAKE_BIT_REVERSE_FUNCTION( function_name, data_type )   \ 
  982    subroutine function_name(n, a); \
 
  983       intrinsic ishft, iand; \
 
  984       data_type, 
dimension(:), 
intent(inout) :: a; \
 
  985       integer, 
intent(in)                    :: n; \
 
  996             a(j + 1) = a(i + 1); \
 
 1000          do while (k <= j); \
 
 1006    end subroutine function_name
 
 1008    make_bit_reverse_function(bit_reverse_complex, sll_comp64)
 
 1016    subroutine bit_reverse_in_pairs(num_pairs, a)
 
 1017       intrinsic ishft, iand
 
 1018       integer, 
intent(in)                    :: num_pairs
 
 1019       sll_real64, 
dimension(0:2*num_pairs - 1), 
intent(inout) :: a
 
 1023       sll_real64, 
dimension(1:2)             :: tmp
 
 1024       sll_assert(sll_f_is_power_of_two(int(num_pairs, i64)))
 
 1027 #define ARRAY(i) a(2*(i):2*(i)+1) 
 1028       do i = 0, num_pairs - 2
 
 1035          k = ishft(num_pairs, -1)
 
 1042    end subroutine bit_reverse_in_pairs
 
 1046    subroutine conjg_in_pairs(n, array)
 
 1047       sll_real64, 
dimension(:) :: array
 
 1050       sll_assert(
size(array) .eq. n)
 
 1053          array(i) = -array(i)
 
 1087    subroutine fft_dit_nr(data, n, twiddles, sign)
 
 1088       sll_comp64, 
dimension(:), 
intent(inout) :: 
data 
 1089       sll_int32, 
intent(in)                   :: sign
 
 1090       sll_comp64, 
dimension(:), 
intent(in)    :: twiddles
 
 1091       sll_int32, 
intent(in)                   :: n
 
 1092       sll_assert(sll_f_is_power_of_two(int(n, i64)))
 
 1093       sll_assert(
size(data) .ge. n)
 
 1094       call fft_dit_nr_aux(
data, n, twiddles, 0, sign)
 
 1095    end subroutine fft_dit_nr
 
 1098    recursive subroutine fft_dit_nr_aux(dat, size, twiddles, &
 
 1099                                        twiddle_index, sign)
 
 1100       intrinsic ishft, conjg
 
 1101       integer, 
intent(in)                             :: size
 
 1103       sll_comp64, 
dimension(0:), 
intent(inout)  :: dat
 
 1105       sll_comp64, 
dimension(0:), 
intent(in)           :: twiddles
 
 1106       integer, 
intent(in)                             :: twiddle_index
 
 1107       integer, 
optional, 
intent(in)                   :: sign
 
 1110       integer                                         :: t_index_new
 
 1114       half = ishft(
size, -1) 
 
 1122       omega = twiddles(twiddle_index)
 
 1125          tmp = dat(j + half)*omega
 
 1126          dat(j + half) = dat(j) - tmp
 
 1127          dat(j) = dat(j) + tmp
 
 1132          t_index_new = ishft(twiddle_index, 1)
 
 1133          call fft_dit_nr_aux(dat(0:half - 1), &
 
 1138          call fft_dit_nr_aux(dat(half:2*half - 1), &
 
 1146    end subroutine fft_dit_nr_aux
 
 1167    recursive subroutine fft_dit_rn_aux(data, &
 
 1172       intrinsic ishft, conjg
 
 1173       sll_int32, 
intent(in)                               :: data_size
 
 1176       sll_comp64, 
dimension(1:data_size), 
intent(inout)   :: 
data 
 1177       sll_comp64, 
dimension(1:data_size/2), 
intent(in)    :: twiddles
 
 1178       integer, 
intent(in)                                 :: twiddle_stride
 
 1179       sll_int32                                           :: new_stride
 
 1180       sll_int32                                           :: jtwiddle
 
 1181       integer, 
intent(in)                                 :: sign
 
 1187       half = ishft(data_size, -1) 
 
 1189          new_stride = twiddle_stride*2
 
 1190          call fft_dit_rn_aux(
data(1:half), half, twiddles, new_stride, sign)
 
 1191          call fft_dit_rn_aux(
data(half + 1:data_size), half, twiddles, new_stride, sign)
 
 1202          omega = twiddles(jtwiddle)
 
 1203          tmp = 
data(j + half)*omega
 
 1204          data(j + half) = 
data(j) - tmp
 
 1205          data(j) = 
data(j) + tmp
 
 1206          jtwiddle = jtwiddle + twiddle_stride
 
 1208    end subroutine fft_dit_rn_aux
 
 1226    recursive subroutine fft_dit_nr_real_array_aux(samples, &
 
 1231       intrinsic ishft, conjg
 
 1233       integer, 
intent(in)                                    :: num_complex
 
 1234       sll_real64, 
dimension(0:2*num_complex - 1), 
intent(inout):: samples
 
 1239       sll_real64, 
dimension(0:), 
intent(in)     :: twiddles
 
 1240       integer, 
intent(in)                                    :: twiddle_index
 
 1241       integer, 
intent(in)                                    :: sign
 
 1246       integer                                                :: t_index_new
 
 1247       sll_real64                                             :: omega_re
 
 1248       sll_real64                                             :: omega_im
 
 1249       sll_real64                                             :: tmp_re
 
 1250       sll_real64                                             :: tmp_im
 
 1251       sll_assert(num_complex .le. 
size(samples))
 
 1252       half = ishft(num_complex, -1) 
 
 1265       omega_re = creal0(twiddles, twiddle_index)
 
 1266       omega_im = cimag0(twiddles, twiddle_index)
 
 1271             creal0(samples, j + half)*omega_re - cimag0(samples, j + half)*omega_im
 
 1273             creal0(samples, j + half)*omega_im + cimag0(samples, j + half)*omega_re
 
 1275          creal0(samples, j + half) = creal0(samples, j) - tmp_re
 
 1276          cimag0(samples, j + half) = cimag0(samples, j) - tmp_im
 
 1278          creal0(samples, j) = creal0(samples, j) + tmp_re
 
 1279          cimag0(samples, j) = cimag0(samples, j) + tmp_im
 
 1284          t_index_new = ishft(twiddle_index, 1)
 
 1285          call fft_dit_nr_real_array_aux(samples(0:2*half - 1), &
 
 1290          call fft_dit_nr_real_array_aux(samples(2*half:4*half - 1), &
 
 1298    end subroutine fft_dit_nr_real_array_aux
 
 1300    recursive subroutine fft_dit_rn_real_array_aux(data, &
 
 1305       intrinsic ishft, conjg
 
 1307       integer, 
intent(in)                                    :: num_complex
 
 1308       sll_real64, 
dimension(1:2*num_complex), 
intent(inout)  :: 
data 
 1313       sll_real64, 
dimension(1:num_complex), 
intent(in)       :: twiddles
 
 1314       sll_int32, 
intent(in)                                  :: twiddle_stride
 
 1315       sll_int32                                              :: new_stride
 
 1316       sll_int32                                              :: jtwiddle
 
 1317       integer, 
intent(in)                                    :: sign
 
 1320       sll_real64                                             :: omega_re
 
 1321       sll_real64                                             :: omega_im
 
 1322       sll_real64                                             :: tmp_re
 
 1323       sll_real64                                             :: tmp_im
 
 1324       sll_assert(num_complex .le. 
size(data))
 
 1328       half = ishft(num_complex, -1) 
 
 1331          new_stride = twiddle_stride*2
 
 1332          call fft_dit_rn_real_array_aux(
data(1:num_complex), &
 
 1337          call fft_dit_rn_real_array_aux(
data(num_complex + 1:2*num_complex), &
 
 1356          omega_re = creal1(twiddles, jtwiddle)
 
 1357          omega_im = cimag1(twiddles, jtwiddle)
 
 1359          tmp_re = creal1(
data, j + half)*omega_re - cimag1(
data, j + half)*omega_im
 
 1360          tmp_im = creal1(
data, j + half)*omega_im + cimag1(
data, j + half)*omega_re
 
 1362          creal1(
data, j + half) = creal1(
data, j) - tmp_re
 
 1363          cimag1(
data, j + half) = cimag1(
data, j) - tmp_im
 
 1365          creal1(
data, j) = creal1(
data, j) + tmp_re
 
 1366          cimag1(
data, j) = cimag1(
data, j) + tmp_im
 
 1367          jtwiddle = jtwiddle + twiddle_stride
 
 1369    end subroutine fft_dit_rn_real_array_aux
 
 1409    subroutine real_data_fft_dit(data, n, twiddles, twiddles_n, sign)
 
 1410       sll_int32, 
intent(in)                      :: n
 
 1411       sll_real64, 
dimension(0:), 
intent(inout) :: 
data 
 1412       sll_real64, 
dimension(0:n/2 - 1), 
intent(in) :: twiddles
 
 1413       sll_real64, 
dimension(0:n - 1), 
intent(in) :: twiddles_n
 
 1414       sll_int32, 
intent(in)                      :: sign
 
 1419       sll_real64                                 :: hn_2mi_re
 
 1420       sll_real64                                 :: hn_2mi_im
 
 1421       sll_real64                                 :: tmp_re
 
 1422       sll_real64                                 :: tmp_im
 
 1423       sll_real64                                 :: tmp2_re
 
 1424       sll_real64                                 :: tmp2_im
 
 1425       sll_real64                                 :: tmp3_re
 
 1426       sll_real64                                 :: tmp3_im
 
 1427       sll_real64                                 :: omega_re
 
 1428       sll_real64                                 :: omega_im
 
 1430       sll_assert(sll_f_is_power_of_two(int(n, i64)))
 
 1431       sll_assert(
size(data) .ge. n)
 
 1432       sll_assert(
size(twiddles) .eq. n/2)
 
 1455          call fft_dit_nr_real_array_aux(
data(0:n - 1), &
 
 1462          call bit_reverse_in_pairs(n_2, 
data(0:n - 1))
 
 1466          stop 
'ERROR IN =REAL_DATA_FFT_DIT= invalid argument sign' 
 1487          hi_re = creal0(
data, i)
 
 1488          hi_im = cimag0(
data, i)
 
 1489          hn_2mi_re = creal0(
data, n_2 - i)
 
 1490          hn_2mi_im = -cimag0(
data, n_2 - i)
 
 1491          omega_re = creal0(twiddles_n, i)
 
 1492          omega_im = s*cimag0(twiddles_n, i) 
 
 1494          tmp_re = 0.5_f64*(hi_re + hn_2mi_re)
 
 1495          tmp_im = 0.5_f64*(hi_im + hn_2mi_im)
 
 1498          tmp2_re = s*0.5_f64*(hi_im - hn_2mi_im)
 
 1499          tmp2_im = -s*0.5_f64*(hi_re - hn_2mi_re)
 
 1501          tmp3_re = tmp2_re*omega_re - tmp2_im*omega_im
 
 1502          tmp3_im = tmp2_re*omega_im + tmp2_im*omega_re
 
 1503          creal0(
data, i) = tmp_re - tmp3_re
 
 1504          cimag0(
data, i) = tmp_im - tmp3_im
 
 1505          creal0(
data, n_2 - i) = tmp_re + tmp3_re
 
 1506          cimag0(
data, n_2 - i) = -tmp_im - tmp3_im
 
 1512          data(0) = tmp_re + 
data(1)   
 
 1513          data(1) = tmp_re - 
data(1)   
 
 1517          data(0) = 0.5_f64*(tmp_re + 
data(1))
 
 1518          data(1) = 0.5_f64*(tmp_re - 
data(1))
 
 1520          call fft_dit_nr_real_array_aux(
data(0:n - 1), &
 
 1527          call bit_reverse_in_pairs(n_2, 
data(0:n - 1))
 
 1530    end subroutine real_data_fft_dit
 
 1537 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_pi
subroutine, public sll_s_fft_get_k_list_r2r_1d(plan, k_list)
Get a list of the k modes in an r2r FFT k_list = [0, 1, 2, ..., n/2, (n+1)/2-1, .....
subroutine, public sll_s_fft_exec_r2c_1d(plan, array_in, array_out)
Compute fast Fourier transform in real to complex mode.
subroutine, public sll_s_fft_free(plan)
Delete a plan.
integer(c_int), parameter, public sll_p_fft_wisdom_only
subroutine, public sll_s_fft_init_c2c_2d(plan, nx, ny, array_in, array_out, direction, normalized, aligned, optimization)
Create new 2d complex to complex plan.
subroutine, public sll_s_fft_init_r2c_1d(plan, nx, array_in, array_out, normalized, aligned, optimization)
Create new 1d real to complex plan for forward FFT.
subroutine, public sll_s_fft_print_defaultlib()
Function to print the FFT library behind the interface.
integer(c_int), parameter, public sll_p_fft_exhaustive
FFTW planning-rigor flag FFTW_EXHAUSTIVE (more optimization than PATIENT) NOTE: planner overwrites th...
subroutine, public sll_s_fft_exec_c2c_2d(plan, array_in, array_out)
Compute fast Fourier transform in complex to complex mode.
subroutine, public sll_s_fft_deallocate_aligned_complex(data)
Function to deallocate an aligned complex array.
subroutine, public sll_s_fft_exec_c2r_1d(plan, array_in, array_out)
Compute fast Fourier transform in complex to real mode.
integer(c_int), parameter, public sll_p_fft_estimate
FFTW planning-rigor flag FFTW_ESTIMATE (simple heuristic for planer) [value 64]. This is our default ...
integer, parameter, public sll_p_fft_forward
Flag to specify forward FFT (negative sign) [value -1].
subroutine, public sll_s_fft_exec_c2r_2d(plan, array_in, array_out)
Compute fast Fourier transform in complex to real mode.
subroutine, public sll_s_fft_init_c2r_1d(plan, nx, array_in, array_out, normalized, aligned, optimization)
Create new 1d complex to real plan for backward FFT.
integer(c_int), parameter, public sll_p_fft_patient
FFTW planning-rigor flag FFTW_PATIENT (more optimizaton than MEASURE) NOTE: planner overwrites the in...
subroutine, public sll_s_fft_set_mode_c2r_1d(plan, data, ck, k)
Subroutine to set a complex mode to the real representation of r2r.
real(c_double) function, dimension(:), pointer, public sll_f_fft_allocate_aligned_real(n)
Function to allocate an aligned real array.
subroutine, public sll_s_fft_get_k_list_r2c_1d(plan, k_list)
Get a list of the k modes in an r2c FFT k_list = [0, 1, 2, ..., n/2].
subroutine, public sll_s_fft_get_k_list_c2c_1d(plan, k_list)
Get a list of the k modes in a c2c FFT k_list = [0, 1, 2, ..., n/2, (n/2+1)-n, ......
subroutine, public sll_s_fft_init_c2r_2d(plan, nx, ny, array_in, array_out, normalized, aligned, optimization)
Create new 2d real to complex plan for backward FFT.
subroutine, public sll_s_fft_init_r2r_1d(plan, nx, array_in, array_out, direction, normalized, aligned, optimization)
Create new 1d real to real plan.
subroutine, public sll_s_fft_exec_c2c_1d(plan, array_in, array_out)
Compute fast Fourier transform in complex to complex mode.
subroutine, public sll_s_fft_exec_r2c_2d(plan, array_in, array_out)
Compute fast Fourier transform in real to complex mode.
subroutine, public sll_s_fft_deallocate_aligned_real(data)
Function to deallocate an aligned real array.
subroutine, public sll_s_fft_init_c2c_1d(plan, nx, array_in, array_out, direction, normalized, aligned, optimization)
Create new 1d complex to complex plan.
subroutine, public sll_s_fft_init_r2c_2d(plan, nx, ny, array_in, array_out, normalized, aligned, optimization)
Create new 2d complex to real plan for forward FFT.
integer, parameter, public sll_p_fft_backward
Flag to specify backward FFT (positive sign) [value 1].
subroutine, public sll_s_fft_exec_r2r_1d(plan, array_in, array_out)
Compute fast Fourier transform in real to real mode.
complex(kind=f64) function, public sll_f_fft_get_mode_r2c_1d(plan, data, k)
Function to reconstruct a complex FFT mode from the data of a r2r transform.
integer(c_int), parameter, public sll_p_fft_measure
FFTW planning-rigor flag FFTW_MEASURE (optimized plan) NOTE: planner overwrites the input array durin...
complex(c_double_complex) function, dimension(:), pointer, public sll_f_fft_allocate_aligned_complex(n)
Function to allocate an aligned complex array.
Some common numerical utilities.
logical function, public sll_f_is_power_of_two(n)
Check if an integer is equal to.
Type for FFT plan in SeLaLib.