NAFPack_Fourier_Transform_dft_compute.f90 Source File


This file depends on

sourcefile~~nafpack_fourier_transform_dft_compute.f90~~EfferentGraph sourcefile~nafpack_fourier_transform_dft_compute.f90 NAFPack_Fourier_Transform_dft_compute.f90 sourcefile~nafpack_fourier_transform_dft.f90 NAFPack_Fourier_Transform_dft.f90 sourcefile~nafpack_fourier_transform_dft_compute.f90->sourcefile~nafpack_fourier_transform_dft.f90 sourcefile~nafpack_fourier_transform.f90 NAFPack_Fourier_Transform.f90 sourcefile~nafpack_fourier_transform_dft.f90->sourcefile~nafpack_fourier_transform.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_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_dft) NAFPack_Fourier_Transform_dft_compute

    implicit none(type, external)

contains

    !=================================================================================
    ! Compute the discrete Fourier transform of a complex signal in simple precision
    !=================================================================================

    module function compute_dft_cmplx_sp(signal, N, loop_method) result(result)
        complex(sp), dimension(:), intent(in) :: signal
        integer(isp), intent(in) :: N
        type(LoopMethod), intent(in) :: loop_method
        complex(sp), dimension(N) :: result
        real(sp), dimension(size(signal)) :: n_vec
        complex(sp) :: omega
        integer(isp) :: i

        if (N == 1) then
            result = signal
        else
            omega = exp(-2 * pi_sp * im_sp / real(N, sp))
            n_vec = [(real(i - 1, sp), i=1, N)]
            if (loop_method%use_do_classic) then
                result = compute_do_classic_cmplx_sp(signal, n_vec, omega, N)
            else if (loop_method%use_vectorized) then
                result = compute_do_vectorized_cmplx_sp(signal, n_vec, omega, N)
            else if (loop_method%use_do_concurrent) then
                result = compute_do_concurrent_cmplx_sp(signal, n_vec, omega, N)
            else if (loop_method%parallel%use_openmp) then
                result = compute_openmp_cmplx_sp(signal, n_vec, omega, N, &
                                                    loop_method%parallel%num_threads)
            end if
        end if

    end function compute_dft_cmplx_sp

    pure function compute_do_classic_cmplx_sp(signal, n_vector, omega, N) result(result)
        complex(sp), dimension(:), intent(in) :: signal
        real(sp), dimension(:), intent(in) :: n_vector
        complex(sp), intent(in) :: omega
        integer(isp), intent(in) :: N
        complex(sp), dimension(N) :: result
        integer(isp) :: i, k

        do i = 1, N
            k = i - 1
            result(i) = sum(signal * omega**(k * n_vector))
        end do

    end function compute_do_classic_cmplx_sp

    pure function compute_do_vectorized_cmplx_sp(signal, n_vector, omega, N) result(result)
        complex(sp), dimension(:), intent(in) :: signal
        real(sp), dimension(:), intent(in) :: n_vector
        complex(sp), intent(in) :: omega
        integer(isp), intent(in) :: N
        complex(sp), dimension(N) :: result
        real(sp), dimension(N) :: k_vector
        complex(sp), dimension(N, N) :: fourier_matrix

        k_vector = n_vector
        fourier_matrix = omega**reshape(spread(k_vector, 2, N) * spread(n_vector, 1, N), [N, N])
        result = matmul(fourier_matrix, signal)

    end function compute_do_vectorized_cmplx_sp

    pure function compute_do_concurrent_cmplx_sp(signal, n_vector, omega, N) result(result)
        complex(sp), dimension(:), intent(in) :: signal
        real(sp), dimension(:), intent(in) :: n_vector
        complex(sp), intent(in) :: omega
        integer(isp), intent(in) :: N
        complex(sp), dimension(N) :: result
        integer(isp) :: i, k

        do concurrent(i=1:N)
            k = i - 1
            result(i) = sum(signal * omega**(k * n_vector))
        end do

    end function compute_do_concurrent_cmplx_sp

    function compute_openmp_cmplx_sp(signal, n_vector, omega, N, threads) result(result)
        complex(sp), dimension(:), intent(in) :: signal
        real(sp), dimension(:), intent(in) :: n_vector
        complex(sp), intent(in) :: omega
        integer(isp), intent(in) :: N, threads
        complex(sp), dimension(N) :: result
        integer(isp) :: i, k

        !$omp parallel do default(none) private(k, i) &
        !$omp& shared(signal, n_vector, omega, result, N) &
        !$omp& num_threads(threads)
        do i = 1, N
            k = i - 1
            result(i) = sum(signal * omega**(k * n_vector))
        end do
        !$omp end parallel do

    end function compute_openmp_cmplx_sp

    !=================================================================================
    ! Compute the discrete Fourier transform of a complex signal in double precision
    !=================================================================================

    module function compute_dft_cmplx_dp(signal, N, loop_method) result(result)
        complex(dp), dimension(:), intent(in) :: signal
        integer(isp), intent(in) :: N
        type(LoopMethod), intent(in) :: loop_method
        complex(dp), dimension(N) :: result
        real(dp), dimension(size(signal)) :: n_vec
        complex(dp) :: omega
        integer(isp) :: i

        if (N == 1) then
            result = signal
        else
            omega = exp(-2 * pi_dp * im_dp / real(N, dp))
            n_vec = [(real(i - 1, dp), i=1, N)]
            if (loop_method%use_do_classic) then
                result = compute_do_classic_cmplx_dp(signal, n_vec, omega, N)
            else if (loop_method%use_vectorized) then
                result = compute_do_vectorized_cmplx_dp(signal, n_vec, omega, N)
            else if (loop_method%use_do_concurrent) then
                result = compute_do_concurrent_cmplx_dp(signal, n_vec, omega, N)
            else if (loop_method%parallel%use_openmp) then
                result = compute_openmp_cmplx_dp(signal, n_vec, omega, N, &
                                                    loop_method%parallel%num_threads)
            end if
        end if

    end function compute_dft_cmplx_dp

    pure module function compute_do_classic_cmplx_dp(signal, n_vector, omega, N) result(result)
        complex(dp), dimension(:), intent(in) :: signal
        real(dp), dimension(:), intent(in) :: n_vector
        complex(dp), intent(in) :: omega
        integer(isp), intent(in) :: N
        complex(dp), dimension(N) :: result
        integer(isp) :: i, k

        do i = 1, N
            k = i - 1
            result(i) = sum(signal * omega**(k * n_vector))
        end do

    end function compute_do_classic_cmplx_dp

    pure module function compute_do_vectorized_cmplx_dp(signal, n_vector, omega, N) result(result)
        complex(dp), dimension(:), intent(in) :: signal
        real(dp), dimension(:), intent(in) :: n_vector
        complex(dp), intent(in) :: omega
        integer(isp), intent(in) :: N
        complex(dp), dimension(N) :: result
        real(dp), dimension(N) :: k_vector
        complex(dp), dimension(N, N) :: fourier_matrix

        k_vector = n_vector
        fourier_matrix = omega**reshape(spread(k_vector, 2, N) * spread(n_vector, 1, N), [N, N])
        result = matmul(fourier_matrix, signal)

    end function compute_do_vectorized_cmplx_dp

    pure module function compute_do_concurrent_cmplx_dp(signal, n_vector, omega, N) result(result)
        complex(dp), dimension(:), intent(in) :: signal
        real(dp), dimension(:), intent(in) :: n_vector
        complex(dp), intent(in) :: omega
        integer(isp), intent(in) :: N
        complex(dp), dimension(N) :: result
        integer(isp) :: i, k

        do concurrent(i=1:N)
            k = i - 1
            result(i) = sum(signal * omega**(k * n_vector))
        end do

    end function compute_do_concurrent_cmplx_dp

    module function compute_openmp_cmplx_dp(signal, n_vector, omega, N, threads) result(result)
        complex(dp), dimension(:), intent(in) :: signal
        real(dp), dimension(:), intent(in) :: n_vector
        complex(dp), intent(in) :: omega
        integer(isp), intent(in) :: N, threads
        complex(dp), dimension(N) :: result
        integer(isp) :: i, k

        !$omp parallel do default(none) private(k, i) &
        !$omp& shared(signal, n_vector, omega, result, N) &
        !$omp& num_threads(threads)
        do i = 1, N
            k = i - 1
            result(i) = sum(signal * omega**(k * n_vector))
        end do
        !$omp end parallel do

    end function compute_openmp_cmplx_dp

    !=================================================================================
    ! Compute the discrete Fourier transform of a complex signal in quadruple precision
    !=================================================================================

    module function compute_dft_cmplx_qp(signal, N, loop_method) result(result)
        complex(qp), dimension(:), intent(in) :: signal
        integer(isp), intent(in) :: N
        type(LoopMethod), intent(in) :: loop_method
        complex(qp), dimension(N) :: result
        real(qp), dimension(size(signal)) :: n_vec
        complex(qp) :: omega
        integer(isp) :: i

        if (N == 1) then
            result = signal
        else
            omega = exp(-2 * pi_qp * im_qp / real(N, qp))
            n_vec = [(real(i - 1, qp), i=1, N)]
            if (loop_method%use_do_classic) then
                result = compute_do_classic_cmplx_qp(signal, n_vec, omega, N)
            else if (loop_method%use_vectorized) then
                result = compute_do_vectorized_cmplx_qp(signal, n_vec, omega, N)
            else if (loop_method%use_do_concurrent) then
                result = compute_do_concurrent_cmplx_qp(signal, n_vec, omega, N)
            else if (loop_method%parallel%use_openmp) then
                result = compute_openmp_cmplx_qp(signal, n_vec, omega, N, &
                                                    loop_method%parallel%num_threads)
            end if
        end if

    end function compute_dft_cmplx_qp

    pure module function compute_do_classic_cmplx_qp(signal, n_vector, omega, N) result(result)
        complex(qp), dimension(:), intent(in) :: signal
        real(qp), dimension(:), intent(in) :: n_vector
        complex(qp), intent(in) :: omega
        integer(isp), intent(in) :: N
        complex(qp), dimension(N) :: result
        integer(isp) :: i, k

        do i = 1, N
            k = i - 1
            result(i) = sum(signal * omega**(k * n_vector))
        end do

    end function compute_do_classic_cmplx_qp

    pure module function compute_do_vectorized_cmplx_qp(signal, n_vector, omega, N) result(result)
        complex(qp), dimension(:), intent(in) :: signal
        real(qp), dimension(:), intent(in) :: n_vector
        complex(qp), intent(in) :: omega
        integer(isp), intent(in) :: N
        complex(qp), dimension(N) :: result
        real(qp), dimension(N) :: k_vector
        complex(qp), dimension(N, N) :: fourier_matrix

        k_vector = n_vector
        fourier_matrix = omega**reshape(spread(k_vector, 2, N) * spread(n_vector, 1, N), [N, N])
        result = matmul(fourier_matrix, signal)

    end function compute_do_vectorized_cmplx_qp

    pure module function compute_do_concurrent_cmplx_qp(signal, n_vector, omega, N) result(result)
        complex(qp), dimension(:), intent(in) :: signal
        real(qp), dimension(:), intent(in) :: n_vector
        complex(qp), intent(in) :: omega
        integer(isp), intent(in) :: N
        complex(qp), dimension(N) :: result
        integer(isp) :: i, k

        do concurrent(i=1:N)
            k = i - 1
            result(i) = sum(signal * omega**(k * n_vector))
        end do

    end function compute_do_concurrent_cmplx_qp

    module function compute_openmp_cmplx_qp(signal, n_vector, omega, N, threads) result(result)
        complex(qp), dimension(:), intent(in) :: signal
        real(qp), dimension(:), intent(in) :: n_vector
        complex(qp), intent(in) :: omega
        integer(isp), intent(in) :: N, threads
        complex(qp), dimension(N) :: result
        integer(isp) :: i, k

        !$omp parallel do default(none) private(k, i) &
        !$omp& shared(signal, n_vector, omega, result, N) &
        !$omp& num_threads(threads)
        do i = 1, N
            k = i - 1
            result(i) = sum(signal * omega**(k * n_vector))
        end do
        !$omp end parallel do

    end function compute_openmp_cmplx_qp

end submodule NAFPack_Fourier_Transform_dft_compute