pub fn fft<F>(
    input: &[FieldElement<F>],
    twiddles: &[FieldElement<F>],
    state: &CudaState,
) -> Result<Vec<FieldElement<F>>, CudaError>
where
    F: IsFFTField,
    F::BaseType: Unpin,
{
    let mut function = state.get_radix2_dit_butterfly(input, twiddles)?;

    const WARP_SIZE: usize = 32;

    let block_size = WARP_SIZE;
    let butterfly_count = input.len() / 2;
    let block_count = (butterfly_count + block_size - 1) / block_size;

    let order = input.len().trailing_zeros();

    for stage in 0..order {
        function.launch(block_count, block_size, stage, butterfly_count as u32)?;
    }

    let output = function.retrieve_result()?;

    bitrev_permutation(output, state)
}
Executes parallel ordered FFT over a slice of two-adic field elements, in CUDA.
Twiddle factors are required to be in bit-reverse order.

"Ordered" means that the input is required to be in natural order, and the output will be
in this order too. Natural order means that input[i] corresponds to the i-th coefficient,
as opposed to bit-reverse order in which input[bit_rev(i)] corresponds to the i-th
coefficient.
crates/math/src/fft/gpu/cuda/ops.rs