Apologies if this is a duplicate, but I can't find a good answer anywhere.
If I have a time-domain cosine signal of the form:
$$x(t) = A\mathrm{cos}(\omega_0 t)$$
Then this will result in an Fourier transform with spectrum:
$$X(\omega)=\frac{A}{2}\delta(\omega-\omega_0) + \frac{A}{2}\delta(\omega+\omega_0) $$
I can generate these results in MATLAB using either fft or doing a summation of DFT. For example:
f = 1; %cosine frequency
A = 20; %cosine amplitude
w = 2*pi*f;
fs = 16; %sample rate in Hz
N = 2; %number of seconds
t = 0:1/fs:(fs*N)-1; %time vector
L = length(t); %length of time
df = fs/L; %frequency spacing
fAxis = (0:df:(fs-df)) - (fs-mod(L,2)*df)/2; %frequency vector
%time domain signal
x = A*cos(w*t);
%FFT of time domain signal
Xfft = fftshift(fft(x)/L);
%DFT of time domain signal
n=(-floor(L/2):1:floor(L/2))';
k=n';
Xdft = (1/L)*sum(x.*exp(-1i*2*pi*n.*k/L),2);
If I take the difference between the modulus of each spectrum, the difference is on the order of 10^-15. So the amplitudes are identical as expected.
However, I was surprised to find that the phases are quite different:
plot(fAxis,angle(Xdft)*180/pi,'--r');; hold on
plot(fAxis,angle(Xfft)*180/pi,'-k','LineWidth',2); hold on
grid on;
xlabel('Frequency (Hz)');
ylabel('Phase Angle (deg)')
legend('DFT','FFT')
set(gca,'FontSize',14)
Result:
The phase of the DFT jumps around between -180 and 180 degrees, which makes sense since the phase should be either -180 or 180 (it also has some zeros as well?). However, I'm confused by the fft phase angle. It looks like it is a constantly increasing function which phase wraps.
I understand that the real and imaginary parts are $\approx 0$ at all values not equal to $\omega_0$. So is this just a case of numerical imprecision at calculating the angle for small numbers? If this were the case, then at 1 Hz (i.e. where the delta spike is) I would expect the fft phase angle to match the DFT phase angle. But they don't there either. Is there something about the fft algorithm that causes the phase to be different when compared to DFT? Or am I making some error somewhere in my code/reasoning?