function [b,bstd,e,estd,yfit,range,bcov] = regress(y,x,range,varargin)
% regress  Ordinary or weighted least-square regression.
%
% Syntax
% =======
%
%     [b,bstd,e,estd,yfit,range,bcov] = regress(y,x)
%     [b,bstd,e,estd,yfit,range,bcov] = regress(y,x,range,...)
%
% Input arguments
% ================
%
% * `y` [ tseries ] - Tseries object with independent (LHS) variables.
%
% * `x` [ tseries] - Tseries object with regressors (RHS) variables.
%
% * `range` [ numeric ] - Date range on which the regression will be run;
% if not specified, the entire range available will be used.
%
% Output arguments
% =================
%
% * `b` [ numeric ] - Vector of estimated regression coefficients.
%
% * `bstd` [ numeric ] - Vector of std errors of the estimates.
%
% * `e` [ tseries ] - Tseries object with the regression residuals.
%
% * `estd` [ numeric ] - Estimate of the std deviation of the regression
% residuals.
%
% * `yfit` [ tseries ] - Tseries object with fitted LHS variables.
%
% * `range` [ numeric ] - The actually used date range.
%
% * `bcov` [ numeric ] - Covariance matrix of the coefficient estimates.
%
% Options
% ========
%
% * `'constant='` [ `true` | *`false`* ] - Include a constant vector in the
% regression; if true the constant will be placed last in the matrix of
% regressors.
%
% * `'weighting='` [ tseries | *empty* ] - Tseries object with weights on
% the observations in the individual periods.
%
% Description
% ============
%
% This function calls the built-in `lscov` function.
%
% Example
% ========
%
%}


% -IRIS Toolbox.
% -Copyright (c) 2007-2012 Jaromir Benes.

if nargin < 3
   range = Inf;
end

% Parse input arguments.
P = inputParser();
P.addRequired('y',@istseries);
P.addRequired('x',@istseries);
P.addRequired('range',@isnumeric);
P.parse(y,x,range);

% Parse options.
options = passvalopt('tseries.regress',varargin{:});

%**************************************************************************

if length(range) == 1 && isinf(range)
   range = get([x,y],'minrange');
else
   range = range(1) : range(end);
end

xdata = rangedata(x,range);
ydata = rangedata(y,range);
if options.constant
   xdata(:,end+1) = 1;
end

if isempty(options.weighting)
   [b,bstd,evar,bcov] = lscov(xdata,ydata);
else
   w = rangedata(options.weighting,range);
   [b,bstd,evar,bcov] = lscov(xdata,ydata,w);
end
estd = sqrt(evar);

if nargout > 2
   e = replace(y,ydata - xdata*b,range(1));
end

if nargout > 4
   yfit = replace(y,xdata*b,range(1));
end

end
