NAFPack_Fourier_Transform_fft_compute_radix2.f90 Source File


This file depends on

sourcefile~~nafpack_fourier_transform_fft_compute_radix2.f90~~EfferentGraph sourcefile~nafpack_fourier_transform_fft_compute_radix2.f90 NAFPack_Fourier_Transform_fft_compute_radix2.f90 sourcefile~nafpack_fourier_transform_fft.f90 NAFPack_Fourier_Transform_fft.f90 sourcefile~nafpack_fourier_transform_fft_compute_radix2.f90->sourcefile~nafpack_fourier_transform_fft.f90 sourcefile~nafpack_fourier_transform.f90 NAFPack_Fourier_Transform.f90 sourcefile~nafpack_fourier_transform_fft.f90->sourcefile~nafpack_fourier_transform.f90 sourcefile~nafpack_memory_management.f90 NAFPack_memory_management.f90 sourcefile~nafpack_fourier_transform_fft.f90->sourcefile~nafpack_memory_management.f90 sourcefile~nafpack_constant.f90 NAFPack_constant.f90 sourcefile~nafpack_fourier_transform.f90->sourcefile~nafpack_constant.f90 sourcefile~nafpack_implementation_type.f90 NAFPack_implementation_type.f90 sourcefile~nafpack_fourier_transform.f90->sourcefile~nafpack_implementation_type.f90 sourcefile~nafpack_kinds.f90 NAFPack_kinds.f90 sourcefile~nafpack_fourier_transform.f90->sourcefile~nafpack_kinds.f90 sourcefile~nafpack_loop_method.f90 NAFPack_loop_method.f90 sourcefile~nafpack_fourier_transform.f90->sourcefile~nafpack_loop_method.f90 sourcefile~nafpack_math_utils.f90 NAFPack_math_utils.f90 sourcefile~nafpack_fourier_transform.f90->sourcefile~nafpack_math_utils.f90 sourcefile~nafpack_memory_management.f90->sourcefile~nafpack_kinds.f90 sourcefile~nafpack_constant.f90->sourcefile~nafpack_kinds.f90 sourcefile~nafpack_implementation_type.f90->sourcefile~nafpack_kinds.f90 sourcefile~nafpack_math_utils.f90->sourcefile~nafpack_kinds.f90

Source Code

submodule(NAFPack_Fourier_Transform:NAFPack_Fourier_Transform_fft) NAFPack_Fourier_Transform_fft_compute_radix2

implicit none(type, external)

contains

recursive module function compute_fft_radix2_recursive_cmplx_sp( &
    signal, plan, stage) result(result)
    complex(sp), dimension(:), intent(in) :: signal
    type(FFTPlan), intent(in) :: plan
    integer(isp), intent(in) :: stage
    complex(sp), dimension(size(signal)) :: result
    complex(sp), dimension(size(signal)/2) :: twiddle, even, odd
    integer(isp) :: N, i0, i1

    N = size(signal)
    i0 = N / 2
    i1 = i0 + 1

    if (N == 1) then
        result = signal
    else if (N == 2) then
        result(1) = signal(1) + signal(2)
        result(2) = signal(1) - signal(2)
        return
    end if

    if (iand(N, N - 1) /= 0) error stop "N must be power of 2"

    twiddle = plan%twiddles(stage)%twiddles_factor
    select case (plan%algorithm%decimation_method%id)
    case (DIT%id)
        even = compute_fft_radix2_recursive_cmplx_sp(signal(1:N:2), plan, stage - 1)
        odd = compute_fft_radix2_recursive_cmplx_sp(signal(2:N:2), plan, stage - 1)

        result(:i0) = even + odd * twiddle
        result(i1:) = even - odd * twiddle
    case (DIF%id)
        even = signal(:i0) + signal(i1:)
        odd = (signal(:i0) - signal(i1:)) * twiddle

        even = compute_fft_radix2_recursive_cmplx_sp(even, plan, stage + 1)
        odd = compute_fft_radix2_recursive_cmplx_sp(odd, plan, stage + 1)

        result(1:N:2) = even
        result(2:N:2) = odd
    end select

end function compute_fft_radix2_recursive_cmplx_sp

module function compute_fft_radix2_iterative_cmplx_sp( &
    signal, plan, stage_params, loop_method) result(result)
    complex(sp), dimension(:), intent(in) :: signal
    type(FFTPlan), intent(in) :: plan
    type(FFTStageParams), intent(in) :: stage_params
    type(LoopMethod), intent(in) :: loop_method
    complex(sp), dimension(plan%N) :: result

    if (loop_method%use_do_classic) then
        result = compute_do_classic_cmplx_sp( &
                 signal, plan, stage_params)
    else if (loop_method%use_vectorized) then
        result = compute_vectorized_cmplx_sp( &
                 signal, plan, stage_params)
    else if (loop_method%use_do_concurrent) then
        result = compute_do_concurrent_cmplx_sp( &
                 signal, plan, stage_params)
    else if (loop_method%parallel%use_openmp) then
        result = compute_openmp_cmplx_sp( &
                 signal, plan, stage_params, &
                 loop_method%parallel%num_threads)
    end if

end function compute_fft_radix2_iterative_cmplx_sp

pure function compute_do_classic_cmplx_sp( &
    signal, plan, stage_params) result(result)
    complex(sp), dimension(:), intent(in) :: signal
    type(FFTPlan), intent(in) :: plan
    type(FFTStageParams), intent(in) :: stage_params
    complex(sp), dimension(plan%N) :: result
    complex(sp) :: even, odd, twiddle
    integer(isp) :: j, block_index, base
    integer(isp) :: i0, i1

    do block_index = 0, stage_params%nb_blocks - 1
        base = block_index * stage_params%current_block_size
        do j = 0, stage_params%block_size - 1
            i0 = base + j + 1
            i1 = i0 + stage_params%block_size
            even = signal(i0)
            odd = signal(i1)

            twiddle = plan%twiddles(stage_params%stage)%twiddles_factor(j + 1)
            select case (plan%algorithm%decimation_method%id)
            case (DIT%id)
                result(i0) = even + twiddle * odd
                result(i1) = even - twiddle * odd
            case (DIF%id)
                result(i0) = even + odd
                result(i1) = (even - odd) * twiddle
            end select
        end do
    end do

end function compute_do_classic_cmplx_sp

pure function compute_vectorized_cmplx_sp( &
    signal, plan, stage_params) result(result)
    complex(sp), dimension(:), intent(in) :: signal
    type(FFTPlan), intent(in) :: plan
    type(FFTStageParams), intent(in) :: stage_params
    complex(sp), dimension(plan%N) :: result
    complex(sp), dimension(stage_params%block_size) :: even, odd, twiddles
    integer(isp), dimension(stage_params%block_size) :: idx, i0, i1
    integer(isp) :: j, block_index, base

    result = signal

    idx = [(j, j=0, stage_params%block_size - 1)]
    twiddles = plan%twiddles(stage_params%stage)%twiddles_factor(idx + 1)

    do block_index = 0, stage_params%nb_blocks - 1
        base = block_index * stage_params%current_block_size
        i0 = base + idx + 1
        i1 = i0 + stage_params%block_size

        even = result(i0)
        odd = result(i1)

        select case (plan%algorithm%decimation_method%id)
        case (DIT%id)
            result(i0) = even + twiddles * odd
            result(i1) = even - twiddles * odd
        case (DIF%id)
            result(i0) = even + odd
            result(i1) = (even - odd) * twiddles
        end select
    end do

end function compute_vectorized_cmplx_sp

pure function compute_do_concurrent_cmplx_sp( &
    signal, plan, stage_params) result(result)
    complex(sp), dimension(:), intent(in) :: signal
    type(FFTPlan), intent(in) :: plan
    type(FFTStageParams), intent(in) :: stage_params
    complex(sp), dimension(plan%N) :: result
    complex(sp) :: even, odd, twiddle
    integer(isp) :: j, base, block_index
    integer(isp) :: i0, i1

    result = signal

    do concurrent(block_index=0:stage_params%nb_blocks - 1, j=0:stage_params%block_size - 1)
        base = block_index * stage_params%current_block_size
        i0 = base + j + 1
        i1 = i0 + stage_params%block_size

        even = result(i0)
        odd = result(i1)
        twiddle = plan%twiddles(stage_params%stage)%twiddles_factor(j + 1)

        select case (plan%algorithm%decimation_method%id)
        case (DIT%id)
            result(i0) = even + twiddle * odd
            result(i1) = even - twiddle * odd
        case (DIF%id)
            result(i0) = even + odd
            result(i1) = (even - odd) * twiddle
        end select
    end do

end function compute_do_concurrent_cmplx_sp

function compute_openmp_cmplx_sp( &
    signal, plan, stage_params, threads) result(result)
    complex(sp), dimension(:), intent(in) :: signal
    type(FFTPlan), intent(in) :: plan
    type(FFTStageParams), intent(in) :: stage_params
    integer(isp), intent(in) :: threads
    complex(sp), dimension(plan%N) :: result
    complex(sp) :: even, odd, twiddle
    integer(isp) :: j, block_index, base
    integer(isp) :: i0, i1

    result = signal

    !$omp parallel do default(none) private(block_index, base, j, even, odd, twiddle, i0, i1) &
    !$omp& shared(result, plan, stage_params) &
    !$omp& num_threads(threads)
    do block_index = 0, stage_params%nb_blocks - 1
        base = block_index * stage_params%current_block_size
        do j = 0, stage_params%block_size - 1
            i0 = base + j + 1
            i1 = i0 + stage_params%block_size
            even = result(i0)
            odd = result(i1)

            twiddle = plan%twiddles(stage_params%stage)%twiddles_factor(j + 1)
            select case (plan%algorithm%decimation_method%id)
            case (DIT%id)
                result(i0) = even + twiddle * odd
                result(i1) = even - twiddle * odd
            case (DIF%id)
                result(i0) = even + odd
                result(i1) = (even - odd) * twiddle
            end select
        end do
    end do
    !$omp end parallel do

end function compute_openmp_cmplx_sp

end submodule NAFPack_Fourier_Transform_fft_compute_radix2