c++fftintel-mkldft

Is there any simple C++ example on how to use Intel MKL FFT?


I need to perform FFT and Inverse-FFT transformations. The input would be vector and matrices of double. Ideally, the output should be an array of std::complex but I can live with double _Complex.

I haven't found any simple example, all Intel examples are doing a lot of things at once without enough comments.

I just want a simple example in C++ taking a vector (or a matrix) of double as input and outputting the FFT-transformed result (ideally with std::complex).


Solution

  • I ended up testing several things and I finally ended up with this three functions that do what I want and that I considered simple examples.

    I tested it against some inputs and I had the good results. I haven't done extensive testing though.

    //Note after each operation status should be 0 on success 
    
    std::vector<std::complex<float>> fft_complex(std::vector<std::complex<float>>& in){
        std::vector<std::complex<float>> out(in.size());
    
        DFTI_DESCRIPTOR_HANDLE descriptor;
        MKL_LONG status;
    
        status = DftiCreateDescriptor(&descriptor, DFTI_SINGLE, DFTI_COMPLEX, 1, in.size()); //Specify size and precision
        status = DftiSetValue(descriptor, DFTI_PLACEMENT, DFTI_NOT_INPLACE); //Out of place FFT
        status = DftiCommitDescriptor(descriptor); //Finalize the descriptor
        status = DftiComputeForward(descriptor, in.data(), out.data()); //Compute the Forward FFT
        status = DftiFreeDescriptor(&descriptor); //Free the descriptor
    
        return out;
    }
    
    std::vector<std::complex<float>> fft_real(std::vector<float>& in_real){
        std::vector<std::complex<float>> in(in_real.size());
    
        std::copy(in_real.begin(), in_real.end(), in.begin());
    
        return fft_complex(in);
    }
    
    std::vector<float> ifft(std::vector<std::complex<float>>& in){
        std::vector<std::complex<float>> out(in.size());
    
        DFTI_DESCRIPTOR_HANDLE descriptor;
        MKL_LONG status;
    
        status = DftiCreateDescriptor(&descriptor, DFTI_SINGLE, DFTI_COMPLEX, 1, in.size()); //Specify size and precision
        status = DftiSetValue(descriptor, DFTI_PLACEMENT, DFTI_NOT_INPLACE); //Out of place FFT
        status = DftiSetValue(descriptor, DFTI_BACKWARD_SCALE, 1.0f / in.size()); //Scale down the output
        status = DftiCommitDescriptor(descriptor); //Finalize the descriptor
        status = DftiComputeBackward(descriptor, in.data(), out.data()); //Compute the Forward FFT
        status = DftiFreeDescriptor(&descriptor); //Free the descriptor
    
        std::vector<float> output(out.size());
    
        for(std::size_t i = 0; i < out.size(); ++i){
            output[i] = out[i].real();
        }
    
        return output;
    }