Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.

inverse fft with real result

mjc
Beginner
983 Views

Let me know if you've heard this before!

I am trying to write an ipps-based function that does something like following MatLab code:

result = ifft( theFT.*conj(theFT) );

Here, theFT is a complex vector and multiplying by its conjugate yields the squared magnitude, which is real. We then get the inverse real fft.

My questions are about formatting the data efficiently for IPP. If I call MagSquared, that gives me a real vector, but I need something in perm (or pack or ccs) format to pass to ippsFFTInv. Is there a convenient function for converting from real to perm? If not, should I write my own function to compute the magnitude and store it in perm format?

thanks for your attention

 

 

0 Kudos
4 Replies
Igor_A_Intel
Employee
983 Views

Hi Mjc,

all packed formats (Pack, Perm, Ccs) are intended for storing complex data. Your vector is real - so the easiest way is to convert it to complex (for example using ippsSampleUp) and then apply complex iFFT instead of developing your own function for RealToPerm conversion.

regards, Igor

0 Kudos
kcang2
Beginner
531 Views

How does ippsSampleUp help? AFAIK it only changes a real signal to another real signal, or a complex signal to another complex signal. Don't think it does real -> complex. 

For my case, I have a filter in Fourier/frequency domain (this is a strict requirement), e.g. a ramp filter.
I want to apply this filter onto an image row using 
ippsMulPerm_32f.

In order to do that, I will have to ippsFFTFwd_RToPerm_32f the image row, 

ippsMulPerm_32f the previous with the filter, and then 
ippsFFTInv_PermToR_32f to get the filtered result.

I can't figure out how to change the filter kernel from non-Perm to Perm format.
Here's what I did which is basically re-arranging the values and splitting the magnitude of the component equally into real and imaginary.

 

    std::vector<float> kernelToPerm(const std::vector<float>& kernel)
    {
        size_t n = kernel.size();
        std::vector<float> res(n);

        // Purely real frequencies
        res[0] = kernel[0];
        res[1] = kernel[n / 2];

        for (int i = 2; i < res.size(); i += 2)
        {
            float energy = kernel[i / 2] * inv_sqrt2;
            res[i] = res[i + 1] = energy;
        }

        return res;
    }

 

 
However, the result is always different than if I use a time-domain filter and forward FFT that filter before multiplying.
The reason I can't use a time-domain filter is a project requirement, where the filter may have additional smoothing performed in Fourier Domain.
0 Kudos
mjc
Beginner
983 Views

That would not be efficient, requiring twice the amount of computation. I have determined that a simple hand-written routine is best.

0 Kudos
kcang2
Beginner
556 Views

Hi, do you mind sharing your implementation?

0 Kudos
Reply