NAFPack_Fourier_Transform_fft.f90 Source File


This file depends on

sourcefile~~nafpack_fourier_transform_fft.f90~~EfferentGraph sourcefile~nafpack_fourier_transform_fft.f90 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

Files dependent on this one

sourcefile~~nafpack_fourier_transform_fft.f90~~AfferentGraph sourcefile~nafpack_fourier_transform_fft.f90 NAFPack_Fourier_Transform_fft.f90 sourcefile~nafpack_fourier_transform_fft_compute_mixed_radix.f90 NAFPack_Fourier_Transform_fft_compute_mixed_radix.f90 sourcefile~nafpack_fourier_transform_fft_compute_mixed_radix.f90->sourcefile~nafpack_fourier_transform_fft.f90 sourcefile~nafpack_fourier_transform_fft_compute_radix2.f90 NAFPack_Fourier_Transform_fft_compute_radix2.f90 sourcefile~nafpack_fourier_transform_fft_compute_radix2.f90->sourcefile~nafpack_fourier_transform_fft.f90 sourcefile~nafpack_fourier_transform_fft_compute_split_radix.f90 NAFPack_Fourier_Transform_fft_compute_split_radix.f90 sourcefile~nafpack_fourier_transform_fft_compute_split_radix.f90->sourcefile~nafpack_fourier_transform_fft.f90

Source Code

submodule(NAFPack_Fourier_Transform) NAFPack_Fourier_Transform_fft

    use NAFPack_memory_management, only: realloc

    implicit none(type, external)

    type FFTStageParams
        integer(isp) :: stage
        integer(isp) :: current_block_size
        integer(isp) :: block_size
        integer(isp) :: nb_blocks
    end type FFTStageParams

    interface
        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(plan%N) :: result
        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
        end function compute_fft_radix2_iterative_cmplx_sp
    end interface

    interface
        recursive module function compute_fft_mixed_radix_recursive_cmplx_sp( &
            signal, plan, stage, radix) result(result)
            complex(sp), dimension(:), intent(in) :: signal
            type(FFTPlan), intent(in) :: plan
            integer(isp), intent(in) :: stage, radix
            complex(sp), dimension(size(signal)) :: result
        end function compute_fft_mixed_radix_recursive_cmplx_sp

        module function compute_fft_mixed_radix_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
        end function compute_fft_mixed_radix_cmplx_sp
    end interface

    interface
        recursive module function compute_fft_split_radix_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
        end function compute_fft_split_radix_recursive_cmplx_sp

        module function compute_fft_split_radix_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
        end function compute_fft_split_radix_cmplx_sp
    end interface

contains

    ! module function fft_plan_create(N) result(plan)
    !     integer(isp), intent(in) :: N
    !     complex(sp), dimension(:), allocatable :: plan
    !     integer(isp), dimension(:), allocatable :: radix_fft

    !     call get_radix(N, radix_fft)

    ! end function fft_plan_create

    module subroutine init_fft_plan_sp(this, N, algorithm, decimation_method)
        class(Fourier_Transform), intent(inout) :: this
        integer(isp), intent(in) :: N
        type(FFTAlgorithm), optional, intent(in) :: algorithm
        type(DecimationMethod), optional, intent(in) :: decimation_method
        integer(isp) :: N_radix

        this%fft_plan%N = N
        this%fft_plan%is_initialized = .true.

        if (present(algorithm)) then
            this%fft_plan%algorithm = algorithm
        else
            this%fft_plan%algorithm = ALG_AUTO
        end if

        select case (this%fft_plan%algorithm%id)
        case (ALG_RADIX2_DIT%id, ALG_RADIX2_DIF%id)
            if (.not. is_power_of_two(N)) &
                error stop "Error in init_fft_plan_sp: N must be a power of two for radix-2 DIT FFT."
            call get_radix_2(this%fft_plan)
            this%fft_plan%use_pure_radix2 = .true.
        case (ALG_SPLIT_DIF%id, ALG_SPLIT_DIT%id)
            if (.not. is_power_of_two(N)) &
                error stop "Error in init_fft_plan_sp: N must be a power of two for split FFT."
            call get_radix_2(this%fft_plan)
            this%fft_plan%use_split_radix = .true.
        case (ALG_MIXED_DIT%id, ALG_MIXED_DIF%id)
            call get_mixed_radix(N, this%fft_plan)
            this%fft_plan%use_mixed_radix = .true.
        case (ALG_AUTO%id)

            if (present(decimation_method)) then
                this%fft_plan%algorithm%decimation_method = decimation_method
            else
                this%fft_plan%algorithm%decimation_method = DIT
            end if

            if (is_power_of_two(N)) then
                call get_radix_2(this%fft_plan)
                this%fft_plan%use_pure_radix2 = .true.
            else
                call get_mixed_radix(N, this%fft_plan)
                this%fft_plan%use_mixed_radix = .true.
            end if

        case (ALG_NONE%id)
            print*,"Error in init_fft_plan_sp: FFT algorithm must be specified."
            error stop
        case default
            print*,"Error in init_fft_plan_sp: Unknown FFT algorithm."
            error stop
        end select

        N_radix = size(this%fft_plan%radix_plan)

        if (this%fft_plan%algorithm%decimation_method%id == DIF%id) then
            this%fft_plan%radix_plan = this%fft_plan%radix_plan(N_radix:1:-1)
        end if

        if (this%fft_plan%use_split_radix) then
            call generate_split_twiddles_sp(this%fft_plan, N_radix)
        else
            call generate_twiddles_sp(this%fft_plan, N_radix)
        end if

        if (this%fft_plan%algorithm%decimation_method%id == DIF%id) then
            if (this%fft_plan%use_split_radix) then
                this%fft_plan%split_radix_twiddles = this%fft_plan%split_radix_twiddles(N_radix:1:-1)
            else
                this%fft_plan%twiddles = this%fft_plan%twiddles(N_radix:1:-1)
            end if
        end if

    end subroutine init_fft_plan_sp

    pure subroutine get_radix_2(plan)
        type(FFTPlan), intent(inout) :: plan
        integer(isp) :: N_radix

        N_radix = power_of_p_exponent(plan%N, 2)
        allocate (plan%radix_plan(N_radix))
        plan%radix_plan = 2

    end subroutine get_radix_2

    pure subroutine get_mixed_radix(N, plan, group_radices)
        integer(isp), intent(in) :: N
        logical, optional, intent(in) :: group_radices
        type(FFTPlan), intent(inout) :: plan
        integer(isp), dimension(:), allocatable :: radix_exponents
        integer(isp), dimension(:), allocatable :: prime_number
        integer(isp) :: N_prime, i, N_temp, N_radix, idx, idx_old
        logical :: group_radices_used

        group_radices_used = .false.
        if (present(group_radices)) group_radices_used = group_radices

        N_temp = N
        prime_number = sieve_of_eratosthenes(N)
        N_prime = size(prime_number, 1)
        allocate (radix_exponents(N_prime))
        radix_exponents = 0

        do i = 1, size(prime_number)
            do while (mod(N_temp, prime_number(i)) == 0)
                radix_exponents(i) = radix_exponents(i) + 1
                N_temp = N_temp / prime_number(i)
            end do
        end do

        if (group_radices_used) then
            N_radix = count(radix_exponents /= 0)
        else
            N_radix = sum(radix_exponents)
        end if
        if (N_temp > 1) N_radix = N_radix + 1

        allocate (plan%radix_plan(N_radix))
        idx = 0
        idx_old = 0

        do i = 1, N_prime
            if (radix_exponents(i) /= 0) then
                if (group_radices_used) then
                    idx = idx + 1
                    plan%radix_plan(idx) = prime_number(i)**radix_exponents(i)
                else
                    idx = idx_old + radix_exponents(i)
                    plan%radix_plan((idx_old) + 1:idx) = prime_number(i)
                    idx_old = idx
                end if
            end if
        end do

        if (N_temp > 1) plan%radix_plan(N_radix) = N_temp

        deallocate (radix_exponents, prime_number)
    end subroutine get_mixed_radix

    pure subroutine generate_twiddles_sp(plan, N_radix)
        type(FFTPlan), intent(inout) :: plan
        integer(isp), intent(in) :: N_radix
        integer(isp), dimension(:), allocatable :: k
        integer(isp) :: i, j, r, block_size, current_block_size
        real(sp) :: sign_factor

        if (plan%algorithm%decimation_method%id == DIF%id) then
            sign_factor = -1.0_sp ! Pour DIF
        else
            sign_factor = -1.0_sp ! Pour DIT (défaut)
        end if

        allocate (plan%twiddles(N_radix))

        block_size = 1
        do i = 1, N_radix
            r = plan%radix_plan(i)
            current_block_size = block_size * r

            plan%twiddles(i)%radix = r
            plan%twiddles(i)%block_size = block_size
            plan%twiddles(i)%current_block_size = current_block_size

            allocate (plan%twiddles(i)%twiddles_factor(block_size))
            allocate (k(0:block_size - 1))
            k = [(j, j=0, block_size - 1)]
            plan%twiddles(i)%twiddles_factor = exp(sign_factor * 2.0_sp * im_sp * pi_sp * k / current_block_size)
            deallocate (k)

            block_size = current_block_size
        end do
    end subroutine generate_twiddles_sp

    subroutine generate_split_twiddles_sp(plan, N_radix)
        type(FFTPlan), intent(inout) :: plan
        integer(isp), intent(in) :: N_radix
        integer(isp), parameter :: MAX_ITER = 20
        integer(isp), dimension(:), allocatable :: tmp_start_indices, tmp_strides
        integer(isp), dimension(:), allocatable :: k
        integer(isp) :: i, j, r, block_size, current_block_size
        real(sp) :: sign_factor
        integer(isp) :: start_index, stride, num_stages, tmp_size

        if (plan%algorithm%decimation_method%id == DIF%id) then
            sign_factor = 1.0_sp
        else
            sign_factor = -1.0_sp
        end if

        allocate (plan%split_radix_twiddles(N_radix))

        current_block_size = 2
        do i = 1, N_radix
            r = plan%radix_plan(i)
            block_size = current_block_size / (2 * r)

            ! Initialize stage parameters
            plan%split_radix_twiddles(i)%radix = r
            plan%split_radix_twiddles(i)%block_size = block_size
            plan%split_radix_twiddles(i)%current_block_size = current_block_size

            ! Allocation and computation of twiddles_Wk and twiddles_W3k
            if (block_size < 1) then
                allocate (plan%split_radix_twiddles(i)%twiddles_Wk(1))
                allocate (plan%split_radix_twiddles(i)%twiddles_W3k(1))
                plan%split_radix_twiddles(i)%twiddles_Wk = (1._sp, 0._sp)
                plan%split_radix_twiddles(i)%twiddles_W3k = (1._sp, 0._sp)
            else
                allocate (plan%split_radix_twiddles(i)%twiddles_Wk(block_size))
                allocate (plan%split_radix_twiddles(i)%twiddles_W3k(block_size))

                allocate (k(0:block_size - 1))
                k = [(j, j=0, block_size - 1)]
                plan%split_radix_twiddles(i)%twiddles_Wk = exp(-2.0_sp * im_sp * pi_sp * k / current_block_size)
                plan%split_radix_twiddles(i)%twiddles_W3k = exp(-2.0_sp * im_sp * pi_sp * 3 * k / current_block_size)
                deallocate (k)
            end if

            ! Allocation and computation of stages split radix
            allocate (plan%split_radix_twiddles(i)%indices(block_size))
            do j = 1, block_size
                allocate (tmp_start_indices(0:MAX_ITER), tmp_strides(0:MAX_ITER))

                num_stages = 0
                start_index = j
                stride = 2 * current_block_size

                tmp_start_indices(num_stages) = start_index
                tmp_strides(num_stages) = stride

                do while (start_index < plan%N)
                    num_stages = num_stages + 1
                    tmp_size = size(tmp_start_indices)
                    if (num_stages > size(tmp_start_indices)) then
                        call realloc(tmp_start_indices, 2 * tmp_size)
                        call realloc(tmp_strides, 2 * tmp_size)
                    end if
                    start_index = 2 * stride - current_block_size + j
                    stride = 4 * stride
                    tmp_start_indices(num_stages) = start_index
                    tmp_strides(num_stages) = stride
                end do
                plan%split_radix_twiddles(i)%indices(j)%num_stages = num_stages

                allocate (plan%split_radix_twiddles(i)%indices(j)%start_indices(0:num_stages))
                allocate (plan%split_radix_twiddles(i)%indices(j)%strides(0:num_stages))
                plan%split_radix_twiddles(i)%indices(j)%start_indices = tmp_start_indices(0:num_stages)
                plan%split_radix_twiddles(i)%indices(j)%strides = tmp_strides(0:num_stages)
                deallocate (tmp_start_indices, tmp_strides)
            end do

            current_block_size = current_block_size * r
        end do
    end subroutine generate_split_twiddles_sp

    module function fft_cmplx_sp(this, signal, loop_method, implementation_type) result(result)
        class(Fourier_Transform), intent(inout) :: this
        complex(sp), dimension(:), intent(in) :: signal
        type(LoopMethod), optional, intent(in) :: loop_method
        type(ImplementationType), optional, intent(in) :: implementation_type
        complex(sp), dimension(:), allocatable :: result
        type(ImplementationType) :: implementation_type_used
        type(LoopMethod) :: loop_method_used

        if (present(loop_method)) then
            loop_method_used = check_loop_method(loop_method)
        else
            loop_method_used = default_loop_method
        end if

        if (present(implementation_type)) then
            implementation_type_used = implementation_type
        else
            implementation_type_used = ITERATIVE
        end if

        if (.not. this%fft_plan%is_initialized) then
            call init_fft_plan_sp(this, size(signal))
        else if (this%fft_plan%N /= size(signal)) then
            print*,"Error in fft_cmplx_sp: FFT plan size does not match signal size."
            error stop
        end if

        select case (implementation_type_used%id)
        case (ITERATIVE%id)
            result = fft_sp_iterative(signal, this%fft_plan, loop_method_used)
        case (recursive%id)
            result = fft_sp_recursive(signal, this%fft_plan)
        end select

    end function fft_cmplx_sp

    function fft_sp_iterative(signal, plan, loop_method) result(result)
        complex(sp), dimension(:), intent(in) :: signal
        type(FFTPlan), intent(in) :: plan
        type(LoopMethod), intent(in) :: loop_method
        complex(sp), dimension(:), allocatable :: result
        complex(sp), dimension(:), allocatable :: signal_reversed
        integer(isp) :: N_radix

        N_radix = size(plan%radix_plan)

        select case (plan%algorithm%decimation_method%id)
        case (DIT%id)
            if (plan%use_pure_radix2 .or. plan%use_split_radix) then
                signal_reversed = bit_reverse(signal, plan%N)
            else if (plan%use_mixed_radix) then
                signal_reversed = digit_reverse(signal, plan%radix_plan)
            else
                print*,"Error in fft_cmplx_sp: Unknown FFT plan type."
                error stop
            end if
            result = compute_fft_sp_iterative(signal_reversed, plan, loop_method)
        case (DIF%id)
            result = compute_fft_sp_iterative(signal, plan, loop_method)
            if (plan%use_pure_radix2 .or. plan%use_split_radix) then
                result = bit_reverse(result, plan%N)
            else if (plan%use_mixed_radix) then
                result = digit_reverse(result, plan%radix_plan(N_radix:1:-1))
            else
                print*,"Error in fft_cmplx_sp: Unknown FFT plan type."
                error stop
            end if
        end select

    end function fft_sp_iterative

    pure function bit_reverse(x, N) result(y)
        complex(sp), dimension(N), intent(in) :: x
        integer(isp), intent(in) :: N
        complex(sp), dimension(N) :: y
        integer(isp) :: i, j, m
        complex(sp) :: tmp

        y = x

        j = 0
        do i = 0, N - 1
            if (i < j) then
                tmp = y(i + 1)
                y(i + 1) = y(j + 1)
                y(j + 1) = tmp
            end if

            m = N / 2
            do while (m > 0 .and. j >= m)
                j = j - m
                m = m / 2
            end do
            j = j + m
        end do

    end function bit_reverse

    function digit_reverse(x, radix_plan) result(y)
        complex(sp), dimension(:), intent(in) :: x
        integer, dimension(:), intent(in) :: radix_plan ! [r1, r2, ..., rm]
        complex(sp), dimension(size(x)) :: y
        integer(isp), dimension(size(radix_plan)) :: d
        integer :: N, m, i, j, idx, rev, factor

        N = size(x)
        m = size(radix_plan)
        do i = 0, N - 1

            idx = i
            do j = m, 1, -1
                d(j) = mod(idx, radix_plan(j))
                idx = idx / radix_plan(j)
            end do

            rev = 0
            factor = 1
            do j = 1, m
                rev = rev + d(j) * factor
                factor = factor * radix_plan(j)
            end do

            y(rev + 1) = x(i + 1)
        end do

    end function digit_reverse

    function compute_fft_sp_iterative(signal, plan, loop_method) result(result)
        complex(sp), dimension(:), intent(in) :: signal
        type(FFTPlan), intent(in) :: plan
        type(LoopMethod), intent(in) :: loop_method
        complex(sp), dimension(:), allocatable :: result
        integer(isp) :: N, num_stages, stage, r
        type(FFTStageParams) :: stage_params

        N = size(signal)
        num_stages = size(plan%radix_plan)
        allocate (result(N))
        result = signal

        do stage = 1, num_stages

            stage_params%stage = stage
            if (allocated(plan%twiddles)) then
                r = plan%twiddles(stage)%radix
                stage_params%block_size = plan%twiddles(stage)%block_size
                stage_params%current_block_size = plan%twiddles(stage)%current_block_size
                stage_params%nb_blocks = N / stage_params%current_block_size
            else if (allocated(plan%split_radix_twiddles)) then
                r = plan%split_radix_twiddles(stage)%radix
                stage_params%block_size = plan%split_radix_twiddles(stage)%block_size
                stage_params%current_block_size = plan%split_radix_twiddles(stage)%current_block_size
                stage_params%nb_blocks = -1
            else
                print*,"Error in compute_fft_sp: Twiddles not allocated."
                error stop
            end if

            if (plan%use_pure_radix2) then
                result = compute_fft_radix2_iterative_cmplx_sp( &
                         result, plan, stage_params, loop_method)
            else if (plan%use_mixed_radix) then
                result = compute_fft_mixed_radix_cmplx_sp( &
                         result, plan, stage_params, loop_method)
            else if (plan%use_split_radix) then
                result = compute_fft_split_radix_cmplx_sp( &
                         result, plan, stage_params, loop_method)
            else
                print*,"Error in compute_fft_sp: Unknown FFT plan type."
                error stop
            end if
        end do

    end function compute_fft_sp_iterative

    function fft_sp_recursive(signal, plan) result(result)
        complex(sp), dimension(:), intent(in) :: signal
        type(FFTPlan), intent(in) :: plan
        complex(sp), dimension(:), allocatable :: result
        integer(isp) :: N, num_stages, radix

        N = size(signal)

        select case (plan%algorithm%decimation_method%id)
        case (DIT%id)
            num_stages = size(plan%radix_plan)
        case (DIF%id)
            num_stages = 1
        end select
        radix = plan%radix_plan(size(plan%radix_plan))

        if (plan%use_pure_radix2) then
            result = compute_fft_radix2_recursive_cmplx_sp( &
                     signal, plan, num_stages)
        else if (plan%use_mixed_radix) then
            result = compute_fft_mixed_radix_recursive_cmplx_sp( &
                     signal, plan, num_stages, radix)
        else if (plan%use_split_radix) then
            result = compute_fft_split_radix_recursive_cmplx_sp( &
                     signal, plan, num_stages)
        else
            print*,"Error in compute_fft_sp: Unknown FFT plan type."
            error stop
        end if

    end function fft_sp_recursive

    pure module subroutine destroy_fft_plan_sp(this)
        class(Fourier_Transform), intent(inout) :: this
        integer(isp) :: i, j

        if (this%fft_plan%is_initialized) then

            if (allocated(this%fft_plan%twiddles)) then
                do i = 1, size(this%fft_plan%twiddles)
                    if (allocated(this%fft_plan%twiddles(i)%twiddles_factor)) then
                        deallocate (this%fft_plan%twiddles(i)%twiddles_factor)
                    end if
                end do
                deallocate (this%fft_plan%twiddles)
            end if

            if (allocated(this%fft_plan%split_radix_twiddles)) then
                do i = 1, size(this%fft_plan%split_radix_twiddles)
                    if (allocated(this%fft_plan%split_radix_twiddles(i)%twiddles_Wk)) then
                        deallocate (this%fft_plan%split_radix_twiddles(i)%twiddles_Wk)
                    end if
                    if (allocated(this%fft_plan%split_radix_twiddles(i)%twiddles_W3k)) then
                        deallocate (this%fft_plan%split_radix_twiddles(i)%twiddles_W3k)
                    end if

                    if (allocated(this%fft_plan%split_radix_twiddles(i)%indices)) then
                        do j = 1, size(this%fft_plan%split_radix_twiddles(i)%indices)
                            if (allocated(this%fft_plan%split_radix_twiddles(i)%indices(j)%start_indices)) then
                                deallocate(this%fft_plan%split_radix_twiddles(i)%indices(j)%start_indices)
                            end if
                            if (allocated(this%fft_plan%split_radix_twiddles(i)%indices(j)%strides)) then
                                deallocate(this%fft_plan%split_radix_twiddles(i)%indices(j)%strides)
                            end if
                        end do
                        deallocate(this%fft_plan%split_radix_twiddles(i)%indices)
                    end if
                end do
                deallocate (this%fft_plan%split_radix_twiddles)
            end if

            if (allocated(this%fft_plan%radix_plan)) then
                deallocate (this%fft_plan%radix_plan)
            end if

            this%fft_plan%N = 0
            this%fft_plan%is_initialized = .false.
            this%fft_plan%use_pure_radix2 = .false.
            this%fft_plan%use_split_radix = .false.
            this%fft_plan%use_mixed_radix = .false.
            this%fft_plan%algorithm = ALG_NONE
        end if
    end subroutine destroy_fft_plan_sp

end submodule NAFPack_Fourier_Transform_fft