%
% ***********************************************************************************
% DFT or N-point DTFT of a discrete-time signal x defined at sample domain n
%
%   examples for DFT computations:
%             dft( x ) -> default n=0:length(x)-1, displays graphs
%             dft( x, n ) -> displays graphs
%             c = dft( x, n ) -> returns the DFT of x defined on n
%             [ c, k ] = dft( x, n ) -> returns the DFT and the freq domain
%   examples for DTFT computations:
%             dft( x, n, N ) -> displays N-point DTFT graphs
%             c = dft( x, n, N ) -> returns the N-point DTFT of x defined on n
%             [ c, k ] = dft( x, n, N ) -> returns the N-point DFT and the freq domain
% ***********************************************************************************
%

%
% Copyright © 21-Nov-2012 George P. Pavlidis® (sepdek@sepdek.net, gpavlid@gmail.com)
%
function varargout = dft( varargin )

	switch nargin
		case 0
			error('NO INPUT ARGUMENTS!');
		case 1
			% compute DFT
			x = varargin{1};
			n = 0:length(x)-1;
			p = 0;
			t = 'Polar';
		case 2
			% compute DFT
			x = varargin{1};
			n = varargin{2};
			p = 0;
			t = 'Polar';
		case 3
			% compute DTFT using DFT
			x = varargin{1};
			n = varargin{2};
			p = varargin{3};
			t = 'Polar';
		case 4
			% compute DTFT using DFT and define the type of complex representation
			x = varargin{1};
			n = varargin{2};
			p = varargin{3};
			t = varargin{4};
	end
		
	if size(x,2)>size(x,1)
		x = transpose( x);
	end
		
	if length( n ) > length( x ),
		warning('Length of n is bigger that the length of x! Trimming n...');
		n = n(1:length(x));
	elseif length( n ) < length( x ),
		warning('Length of n is smaller that the length of x! Trimming x...');
		x = x(1:length(n));
	end
	
	N = length( x );
	g = dft_basis( N, 1);
	c = g'*x;
	if mod(N,2)==0,
		k = -(N/2):(N/2)-1;
	else
		k = -(N-1)/2:(N-1)/2;
	end
	if p~=0
		G = dft_basis( p, 1);
		C = G'*[ x; zeros(p-N,1)];
		if mod(N,2)==0,
			K = -(p/2):(p/2)-1;
		else
			K = -(p-1)/2:(p-1)/2;
		end
	end
	
	switch nargout
		case 0
			if p==0
				subplot(311);
				stem( n, x);
				axis tight;
				grid on;
				title('Discrete signal');
				xlabel('n');
				subplot(312);
				if strcmpi( t, 'POLAR')
					stem( 2*pi*k/N, abs( fftshift(c)));
					title('Magnitude of DTFT');
				else
					stem( 2*pi*k/N, real( fftshift(c)));
					title('Real part of DTFT');
				end
				axis tight;
				grid on;
				title('Magnitude of DFT');
				xlabel('k');
				subplot(313);
				if strcmpi( t, 'POLAR')
					stem( 2*pi*k/N, angle( fftshift(c)));
					title('Phase shift of DFT');
				else
					stem( 2*pi*k/N, imag(fftshift(c)));
					title('Imaginary part of DTFT');
				end
				axis tight;
				grid on;
				xlabel('k');
			else
				subplot(311);
				stem( n, x);
				axis tight;
				grid on;
				title('Discrete signal');
				xlabel('n');
				subplot(312);
				if strcmpi( t, 'POLAR')
					plot( 2*pi*K/p, abs( fftshift(C)));
					title('Magnitude of DTFT');
				else
					plot( 2*pi*K/p, real(fftshift(C)));
					title('Real part of DTFT');
				end
				hold on;
				if strcmpi( t, 'POLAR')
					plot( 2*pi*k/N, abs( fftshift(c)), 'o');
					title('Magnitude of DTFT');
				else
					plot( 2*pi*k/N, real(fftshift(C)), 'o');
					title('Real part of DTFT');
				end
				hold off;
				axis tight;
				grid on;
				xlabel('k')
				legend('DTFT','DFT');
				subplot(313);
				if strcmpi( t, 'POLAR')
					plot( 2*pi*K/p, angle( fftshift(C)));
					title('Phase shift of DTFT');
				else
					plot( 2*pi*K/p, imag( fftshift(C)));
					title('Imaginary part of DTFT');
				end
				hold on;
				if strcmpi( t, 'POLAR')
					plot( 2*pi*k/N, angle( fftshift(c)), 'o');
					title('Phase shift of DTFT');
				else
					plot( 2*pi*k/N, imag( fftshift(c)), 'o');
					title('Imaginary part of DTFT');
				end
				hold off;
				axis tight;
				grid on;
				xlabel('k');
			end
		case 1,
			if p==0
				varargout{1} = c;
			else
				varargout{1} = C;
			end
		case 2,
			if p==0
				varargout{1} = c;
				varargout{2} = k;
			else
				varargout{1} = C;
				varargout{2} = K;
			end
	end

		