简体   繁体   中英

Why does my own implementation of Fast Fourier Transform in N dimensions give different results than NumPy's?

I've written the following code for the N-dimensional Fast Fourier Transform but it doesn't give me the same result as numpy's function.

def nffourier(f, direct):
    dim = f.ndim  
    N = f.shape
    G = np.zeros(f.shape, dtype=complex)
    G = f
    
    for k in range(dim):
        for i in range(N[k]):
            aux = G[(slice(None),) * (k) + (i,)]
            trans = ffourier(aux, direct)
            G[(slice(None),) * (k) + (i,)] = trans
            
    return G

My code for calculating FFT in 1d is the following:

def ffourier(f, direct):
    N = len(f)
    
    M = int(m.log(N)/m.log(2))
        
    G = []
    order = []
    
    for i in range(N):
        order.append(int(bin(i)[2:]))
    
    digitos = len(aux)
    for i in range(N):
        contenido_aux = str(int(order[i]))
        aux = len(str(order[i]))
        if(aux<digitos):
            añadir=digitos-aux
            for k in range(añadir):
                contenido_aux = '0'+contenido_aux
        G.append(contenido_aux)
    for i in range(len(G)):
        G[i] = G[i][::-1]
    

    for i in range(len(G)):
        G[i] = int(G[i], 2)
    for i in range(len(G)):
        G[i] = f[G[i]]
    

    
   
    if direct == False:
        signo = 1
    else:
        signo = -1


    kmax = 1
    kmax = int(kmax)
    for alfa in range(1,M+1):
        w1 = np.exp(signo*1j*2*m.pi/(2**alfa))
        kmax = int(2*kmax)
        W = 1
        for k in range(0, int(kmax/2)-1+1):
            for s in range(0, N-1+1, int(kmax)):
                T0 = G[s+k]
                T1 = G[s+k+int(kmax/2)]*W
                G[s+k]=T0+T1
                G[s+k+int(kmax/2)]=T0-T1
            W=W*w1
    cte = 1/m.sqrt(N)
    for i in range(0, N-1+1):
        G[i] = G[i]*cte 
    return G

The fundamentals of it is quite hard to explain, it's based on bit inversion, but I've checked it works properly, so the problem is with the N dimensional code.

Your indexing, G[(slice(None),) * (k) + (i,)] , is the same as G[:,:,i,:,:] for a 5D array if k is 2. This is not the indexing you want to generate. You need to extract a single 1D sub-array, and loop over all such sub-arrays.

I think the simplest way to get this to work for an arbitrary N-dimensional array is to permute the array dimensions in a loop over N, so that you're always applying the 1D FFT over the last dimension, and flattening the remainder of the dimensions to easily loop over them. Something like this (not tested):

def nffourier(f, direct):
    dim = f.ndim  
    G = f.astype(complex)
    
    for k in range(dim):
        G = np.moveaxis(G, 0, -1)  # shifts the dimensions by one to the left
        shape = G.shape
        m = shape[-1]
        G = np.reshape(G, (-1, m))  # flattens all but last dimension
        m = G.shape[0]
        for i in range(m):          # loop over first dimension
            G[i, :] = ffourier(G[i, :], direct)  # apply over last dimension
        G = np.reshape(G, shape)    # return to original shape
    
    # After applying moveaxis dim times, G should have the same it had at the start
    return G

(Note also, as we already discussed in the comments, that the G = f line causes the output array G to be of the same type as f , likely not complex, and so will cause errors also.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM