15

Does anyone know if there is any free and open source library that has implemented these two functions the way they are defined in matlab?

Thanks

Derek
  • 11,715
  • 32
  • 127
  • 228
  • I cast my close vote in error. Although [this question](http://stackoverflow.com/questions/5735720/effcient-way-to-do-fft-shift-in-matlab-without-using-fftshift-function/5740442#5740442) is similar, your question is not exactly a duplicate, as you're asking for free/open libraries, whereas the other person just wanted to port MATLAB's implementation to C. – abcd May 06 '11 at 18:39
  • Some convenient shift C++ functions can be found in FFTW++: https://github.com/dealias/fftwpp/blob/master/fftw%2B%2B.h – Herpes Free Engineer Apr 08 '18 at 17:51
  • In addition to the above, NFFT library provides shift functions in C: https://github.com/NFFT/nfft/blob/cb72c9ada6bbe720c8b4b377d553b02b262ec31d/kernel/util/vector3.c – Herpes Free Engineer Apr 09 '18 at 16:04

10 Answers10

16

FFTHIFT / IFFTSHIFT is a fancy way of doing CIRCSHIFT. You can verify that FFTSHIFT can be rewritten as CIRCSHIFT as following. You can define macros in C/C++ to punt FFTSHIFT to CIRCSHIFT.

A = rand(m, n);
mm = floor(m / 2);
nn = floor(n / 2);
% All three of the following should provide zeros.
circshift(A,[mm, nn]) - fftshift(A)
circshift(A,[mm,  0]) - fftshift(A, 1)
circshift(A,[ 0, nn]) - fftshift(A, 2) 

Similar equivalents can be found for IFFTSHIFT.

Circular shift can be implemented very simply with the following code (Can be improved with parallel versions ofcourse).

template<class ty>
void circshift(ty *out, const ty *in, int xdim, int ydim, int xshift, int yshift)
{
  for (int i = 0; i < xdim; i++) {
    int ii = (i + xshift) % xdim;
    for (int j = 0; j < ydim; j++) {
      int jj = (j + yshift) % ydim;
      out[ii * ydim + jj] = in[i * ydim + j];
    }
  }
}

And then

#define fftshift(out, in, x, y) circshift(out, in, x, y, (x/2), (y/2))
#define ifftshift(out, in, x, y) circshift(out, in, x, y, ((x+1)/2), ((y+1)/2))

This was done a bit impromptu. Bear with me if there are any formatting / syntactical problems.

Pavan Yalamanchili
  • 12,021
  • 2
  • 35
  • 55
7

Possible this code may help. It perform fftshift/ifftshift only for 1D array within one buffer. Algorithm of forward and backward fftshift for even number of elements is fully identical.

void swap(complex *v1, complex *v2)
{
    complex tmp = *v1;
    *v1 = *v2;
    *v2 = tmp;
}

void fftshift(complex *data, int count)
{
    int k = 0;
    int c = (int) floor((float)count/2);
    // For odd and for even numbers of element use different algorithm
    if (count % 2 == 0)
    {
        for (k = 0; k < c; k++)
            swap(&data[k], &data[k+c]);
    }
    else
    {
        complex tmp = data[0];
        for (k = 0; k < c; k++)
        {
            data[k] = data[c + k + 1];
            data[c + k + 1] = data[k + 1];
        }
        data[c] = tmp;
    }
}

void ifftshift(complex *data, int count)
{
    int k = 0;
    int c = (int) floor((float)count/2);
    if (count % 2 == 0)
    {
        for (k = 0; k < c; k++)
            swap(&data[k], &data[k+c]);
    }
    else
    {
        complex tmp = data[count - 1];
        for (k = c-1; k >= 0; k--)
        {
            data[c + k + 1] = data[k];
            data[k] = data[c + k];
        }
        data[c] = tmp;
    }
}

UPDATED: Also FFT library (including fftshift operations) for arbitrary points number could be found in Optolithium (under the OptolithiumC/libs/fourier)

mblw
  • 1,762
  • 1
  • 19
  • 28
5

Normally, centering the FFT is done with v(k)=v(k)*(-1)**k in the time domain. Shifting in the frequency domain is a poor substitute, for mathematical reasons and for computational efficiency. See pp 27 of: http://show.docjava.com/pub/document/jot/v8n6.pdf

I am not sure why Matlab documentation does it the way they do, they give no technical reference.

Paul R
  • 208,748
  • 37
  • 389
  • 560
Douglas Lyon
  • 67
  • 1
  • 1
  • 1
    +1. In terms of code, for a row-vector `x`, `fftshift(fft(x))` is to within machine-precision of `fft(x .* (-1).^(0 : numel(x) - 1))`. A similar result holds for `ifftshift` (and to the two-dimensional case). If the input to the FFT is being calculated, it’s sometimes very easy to slip in a sign-alternation before the FFT, and this can be much faster than shifting memory after the FFT. – Ahmed Fasih Nov 05 '16 at 02:32
  • Does this also work for the case where the number of elements is odd? – Dirklinux Dec 05 '16 at 16:24
  • 1
    No, it does not work for odd number of elements. For odd number of elements you need to multiply the input by `exp(i*pi*numel(x)/(numel(x)+1)*(0 : numel(x) - 1))`. But I get into numerical precision issues when I do this. Note that the result is complex, even for real input, so you won't be able to do that in place. For odd-sized signals, it's better to shift data around in the Fourier domain. I don't see why it's a poor substitute, there certainly are no mathematical reasons that I can see! – Cris Luengo Mar 12 '17 at 05:05
4

Or you can do it yourself by typing type fftshift and recoding that in C++. It's not that complicated of Matlab code.

Edit: I've noticed that this answer has been down-voted a few times recently and commented on in a negative way. I recall a time when type fftshift was more revealing than the current implementation, but I could be wrong. If I could delete the answer, I would as it seems no longer relevant.

Here is a version (courtesy of Octave) that implements it without circshift.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
Chris A.
  • 6,817
  • 2
  • 25
  • 43
  • 3
    `fftshift` is implemented as a call to `circshift`, and `circshift` is a built-in function, so you can't see how it's coded. This is a useless answer. – Cris Luengo Mar 12 '17 at 05:06
3

I tested the code provided here and made an example project to test them. For 1D code one can simply use std::rotate

template <typename _Real>
static inline
void rotshift(complex<_Real> * complexVector, const size_t count)
{
    int center = (int) floor((float)count/2);
    if (count % 2 != 0) {
        center++;
    }
    // odd: 012 34 changes to 34 012
    std::rotate(complexVector,complexVector + center,complexVector + count);
}

template <typename _Real>
static inline
void irotshift(complex<_Real> * complexVector, const size_t count)
{
    int center = (int) floor((float)count/2);
    // odd: 01 234 changes to 234 01
    std::rotate(complexVector,complexVector +center,complexVector + count);
}

I prefer using std::rotate over the code from Alexei due to its simplicity.

For 2D it gets more complicated. For even numbers it is basically a flip left right and flip upside down. For odd it is the circshift algorithm:

//    A =
//    1     2     3
//    4     5     6
//    7     8     9


//    fftshift2D(A)
//    9  |   7     8
//    --------------
//    3  |   1     2
//    6  |   4     5


//    ifftshift2D(A)
//    5     6   |  4
//    8     9   |  7
//    --------------
//    2     3   |  1

Here I implemented the circshift code with an interface using only one array for in and output. For even numbers only a single array is required, for odd numbers a second array is temporarily created and copied back to the input array. This causes a performance decrease because of the additional time for copying the array.

template<class _Real>
static inline
void fftshift2D(complex<_Real> *data, size_t xdim, size_t ydim)
{
    size_t xshift = xdim / 2;
    size_t yshift = ydim / 2;
    if ((xdim*ydim) % 2 != 0) {
        // temp output array
        std::vector<complex<_Real> > out;
        out.resize(xdim * ydim);
        for (size_t x = 0; x < xdim; x++) {
            size_t outX = (x + xshift) % xdim;
            for (size_t y = 0; y < ydim; y++) {
                size_t outY = (y + yshift) % ydim;
                // row-major order
                out[outX + xdim * outY] = data[x + xdim * y];
            }
        }
        // copy out back to data
        copy(out.begin(), out.end(), &data[0]);
        }
    else {
        // in and output array are the same,
        // values are exchanged using swap
        for (size_t x = 0; x < xdim; x++) {
            size_t outX = (x + xshift) % xdim;
            for (size_t y = 0; y < yshift; y++) {
                size_t outY = (y + yshift) % ydim;
                // row-major order
                swap(data[outX + xdim * outY], data[x + xdim * y]);
            }
        }
    }
}

template<class _Real>
static inline
void ifftshift2D(complex<_Real> *data, size_t xdim, size_t ydim)
{
    size_t xshift = xdim / 2;
    if (xdim % 2 != 0) {
        xshift++;
    }
    size_t yshift = ydim / 2;
    if (ydim % 2 != 0) {
        yshift++;
    }
    if ((xdim*ydim) % 2 != 0) {
        // temp output array
        std::vector<complex<_Real> > out;
        out.resize(xdim * ydim);
        for (size_t x = 0; x < xdim; x++) {
            size_t outX = (x + xshift) % xdim;
            for (size_t y = 0; y < ydim; y++) {
                size_t outY = (y + yshift) % ydim;
                // row-major order
                out[outX + xdim * outY] = data[x + xdim * y];
            }
        }
        // copy out back to data
        copy(out.begin(), out.end(), &data[0]);
        }
    else {
        // in and output array are the same,
        // values are exchanged using swap
        for (size_t x = 0; x < xdim; x++) {
            size_t outX = (x + xshift) % xdim;
            for (size_t y = 0; y < yshift; y++) {
                size_t outY = (y + yshift) % ydim;
                // row-major order
                swap(data[outX + xdim * outY], data[x + xdim * y]);
            }
        }
    }
}
Matthias Pospiech
  • 3,130
  • 18
  • 55
  • 76
1

You could also use arrayfire's shift function as replacement for Matlab's circshift and re-implement the rest of the code. This could be useful if you are interested in any of the other features of AF anyway (such as portability to GPU by simply changing a linker flag).

However if all your code is meant to be run on the CPU and is quite sophisticated or you don't want to use any other data format (AF requires af::arrays) stick with one of the other options.

I ended up changing to AF because I would have had to re-implement fftshift as an OpenCL kernel otherwise back in the time.

E. Odj
  • 81
  • 5
1

Notice: There are better answers provided, I just keep this here for a while for... I do not know what.

Try this:

template<class T> void ifftShift(T *out, const T* in, size_t nx, size_t ny)
{
    const size_t hlen1 = (ny+1)/2;
    const size_t hlen2 = ny/2;
    const size_t shft1 = ((nx+1)/2)*ny + hlen1;
    const size_t shft2 = (nx/2)*ny + hlen2;

    const T* src = in;
    for(T* tgt = out; tgt < out + shft1 - hlen1; tgt += ny, src += ny) { // (nx+1)/2 times
        copy(src, src+hlen1, tgt + shft2);          //1->4
        copy(src+hlen1, src+ny, tgt+shft2-hlen2); } //2->3
    src = in;
    for(T* tgt = out; tgt < out + shft2 - hlen2; tgt += ny, src += ny ){ // nx/2 times
        copy(src+shft1, src+shft1+hlen2, tgt);         //4->1
        copy(src+shft1-hlen1, src+shft1, tgt+hlen2); } //3->2
};

For matrices with even dimensions you can do it in-place, just passing the same pointer into in and out parameters.

Also note that for 1D arrays fftshift is just std::rotate.

Slava
  • 1,528
  • 1
  • 15
  • 23
  • Can you provide an example for this code. IT is not really obvious what it computes and does with a 1D or 2D array. – Matthias Pospiech Mar 11 '16 at 07:02
  • this is for 2d arrays only. What it does is copying by half-rows between the source and destination arrays knowing the proper quarters. I myself no longer like this piece of code actually. I would suggest to start from Pavan Yalamanchili answer, just do not define macros where a funciton would do. – Slava Mar 11 '16 at 09:46
  • The problem with that example is, that it requires an in and out array. However for large matrices this requires to allocate extra memory which I would like to avoid. What I do like is that it is more general solution. – Matthias Pospiech Mar 15 '16 at 19:42
  • For even dimensions you can put the same matrix for in and out. But really, there are better answers here. Like to do it in real space domain for instance (although I do not like the reasoning there, the idea itself is worthy). – Slava Mar 16 '16 at 10:04
0

It will give equivalent result to ifftshift in matlab

ifftshift(vector< vector <double> > Hlow,int RowLineSpace, int ColumnLineSpace)
{
   int pivotRow=floor(RowLineSpace/2);
   int pivotCol=floor(ColumnLineSpace/2);

   for(int i=pivotRow;i<RowLineSpace;i++){
      for(int j=0;j<ColumnLineSpace;j++){
        double temp=Hlow.at(i).at(j);
        second.push_back(temp);
      }
    ifftShiftRow.push_back(second);
    second.clear();
}

for(int i=0;i<pivotRow;i++){
        for(int j=0;j<ColumnLineSpace;j++){
            double temp=Hlow.at(i).at(j);
            first.push_back(temp);
        }
        ifftShiftRow.push_back(first);
        first.clear();
    }


 double** arr = new double*[RowLineSpace];
  for(int i = 0; i < RowLineSpace; ++i)
      arr[i] = new double[ColumnLineSpace];
  int i1=0,j1=0;
  for(int j=pivotCol;j<ColumnLineSpace;j++){
        for(int i=0;i<RowLineSpace;i++){
            double temp2=ifftShiftRow.at(i).at(j);
            arr[i1][j1]=temp2;
            i1++;
        }
        j1++;
        i1=0;
    }
 for(int j=0;j<pivotCol;j++){
    for(int i=0;i<RowLineSpace;i++){
        double temp1=ifftShiftRow.at(i).at(j);
            arr[i1][j1]=temp1;
                i1++;

            }

           j1++;
            i1=0;
        }

for(int i=0;i<RowLineSpace;i++){
    for(int j=0;j<ColumnLineSpace;j++){
        double value=arr[i][j];
        temp.push_back(value);

    }
    ifftShiftLow.push_back(temp);
    temp.clear();
}
    return ifftShiftLow;


 }
-1

You can use kissfft. It's reasonable fast, extremely simple to use, and free. Arranging the output like you want it requires only to:

a) shift by (-dim_x/2, -dim_y/2, ...), with periodic boundary conditions

b) FFT or IFFT

c) shift back by (dim_x/2, dim_y/2, ...) , with periodic boundary conditions

d) scale ? (according to your needs IFFT*FFT will scale the function by dim_x*dim_y*... by default)

FFox
  • 1,550
  • 2
  • 17
  • 26
-1

Octave uses fftw to implement (i)fftshift.

nmichaels
  • 49,466
  • 12
  • 107
  • 135
  • 5
    fftw doesnt have any API to the shifting functions I dont think – Derek May 06 '11 at 18:20
  • There is no need to go into the frequency domain and back again in order to perform these simple shifting operations. – Paul R Jan 10 '17 at 14:17