function x = windex(x,w,range,varargin)
% windex  Simple weighted or Divisia index.
%
% Syntax
% =======
%
%     y = windex(x,w,range)
%
% Input arguments
% ================
%
% * `x` [ tseries ] - Input times series.
%
% * `w` [ tseries | numeric ] - Fixed or time-varying weights on the input
% time series.
%
% * `range` [ numeric ] - Range on which the Divisia index is computed.
%
% Output arguments
% =================
%
% * `y` [ tseries ] - Weighted index based on `x`.
%
% Options
% ========
%
% * `'method='` [ 'divisia' | *'simple'* ] - Weighting method.
%
% * `'log='` [ `true` | *`false`* ] - Logarithmise the input data before
% computing the index, delogarithmise the output data.
%
% Description
% ============
%
% Example
% ========
% -IRIS Toolbox.
% -Copyright (c) 2007-2012 Jaromir Benes.

if nargin < 3
    range = Inf;
end

P = inputParser();
P.addRequired('x',@istseries);
P.addRequired('w',@(x) isnumeric(x) || istseries(x));
P.addRequired('range',@isnumeric);
P.parse(x,w,range);

options = passvalopt('tseries.windex',varargin{:});

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

x.data = x.data(:,:);
temp = x;
if istseries(w)
    w.data = w.data(:,:);
    temp = mytrim([temp,w]);
end

% Generate the range.
range = specrange(temp,range);
data = rangedata(x,range);
nper = length(range);

% Get the weights.
if istseries(w)
    w = rangedata(w,range);
elseif size(w,1) == 1
    w = w(ones([1,nper]),:);
end
w = w(:,:);

wsum = sum(w,2);
if size(w,2) == size(data,2)
    % Normalise weights.
    for i = 1 : size(w,2)
        w(:,i) = w(:,i) ./ wsum(:);
    end
elseif size(w,2) == size(data,2)-1
    % Add the last weight.
    w = [w,1-wsum];
end

switch lower(options.method)
    case 'simple'
        if options.log
            data = log(data);
        end
        data = sum(w .* data,2);
        if options.log
            data = exp(data);
        end
    case 'divisia'
        % Compute the average weights between t and t-1.
        wavg = (w(2:end,:) + w(1:end-1,:))/2;
        % Construct the Divisia index.
        data = sum(wavg .* log(data(2:end,:)./data(1:end-1,:)),2);
        % Set the first observation to 1 and cumulate back.
        data = exp(cumsum([0;data]));
end

x.data = data;
x.start = range(1);
x.Comment = {''};

end