I am converting a python code into MATLAB and one of the code uses numpy rfft. In the documentation of numpy, it says real input.
Compute the one-dime
The real FFT in numpy uses the fact that the fourier transform of a real valued function is so to say "skew-symmetric", that is the value at frequency k
is the complex conjugate of the value at frequency N-k
for k=1..N-1
(the correct term is Hermitian). Therefore rfft
returns only the part of the result that corresponds to nonpositive frequences.
For an input of size N
the rfft
function returns the part of the FFT output corresponding to frequences at or below N/2
. Therefore the output of rfft
is of size N/2+1
if N
is even (all frequences from 0
to N/2
), or (N+1)/2
if N
is odd (all frequences from 0 to (N-1)/2
). Observe that the function floor(n/2+1)
returns the correct output size for both even and odd input sizes.
So to reproduce rfft
in matlab
function rfft = rfft(a)
ffta = fft(a);
rfft = ffta(1:(floor(length(ffta)/2)+1));
end
For example
a = [1,1,1,1,-1,-1,-1,-1];
rffta = rfft(a)
would produce
rffta =
Columns 1 through 3:
0.00000 + 0.00000i 2.00000 - 4.82843i 0.00000 + 0.00000i
Columns 4 through 5:
2.00000 - 0.82843i 0.00000 + 0.00000i
Now compare that with python
>>> np.fft.rfft(a)
array([ 0.+0.j , 2.-4.82842712j, 0.-0.j ,
2.-0.82842712j, 0.+0.j ])
To reproduce basic functionality of irfft
you need to recover the missing frequences from rfft
output. If the desired output length is even, the output length can be computed from the input length as 2 (m - 1)
. Otherwise it should be 2 (m - 1) + 1
.
The following code would work.
function irfft = irfft(x,even=true)
n = 0; % the output length
s = 0; % the variable that will hold the index of the highest
% frequency below N/2, s = floor((n+1)/2)
if (even)
n = 2 * (length(x) - 1 );
s = length(x) - 1;
else
n = 2 * (length(x) - 1 )+1;
s = length(x);
endif
xn = zeros(1,n);
xn(1:length(x)) = x;
xn(length(x)+1:n) = conj(x(s:-1:2));
irfft = ifft(xn);
end
Now you should have
>> irfft(rfft(a))
ans =
1.00000 1.00000 1.00000 1.00000 -1.00000 -1.00000 -1.00000 -1.00000
and also
abs( irfft(rfft(a)) - a ) < 1e-15
For odd output length you get
>> irfft(rfft(a(1:7)),even=false)
ans =
1.0000 1.0000 1.0000 1.0000 -1.0000 -1.0000 -1.0000