function M = slpweval(X1, X2, f, varargin)
%SLPWEVAL Perform pairwise computation
%
% $ Syntax $
% - M = slpweval(X1, X2, f)
% - M = slpweval(X1, X2, f, ...)
%
% $ Arguments $
% - X1: the matrix of vectors serving as first argument of f
% - X2: the matrix of vectors serving as second argument of f
% - f: the function maps two vectors to a single scalar value
% - M: the matrix of pairwise evaluaton results
%
% $ Description $
% - M = slpweval(X1, X2, f) takes vector arguments from X1 and X2, and
% computes the pairwise evaluation result with f. The vectors in X1
% and X2 are stored in a column-wise manner. Suppose X1 and X2 have
% m and n columns respectively, then the resultant matrix M would be
% of size m x n, with the M(i, j) = f(X1(:,i), X2(:,j)).
%
% - M = slpweval(X1, X2, f, ...) conducts the computation with extra
% parameters to f, i.e. M(i, j) = f(X1(:,i), X2(:,j), ...).
%
% $ Remarks $
% - The vector length of the vectors in X1 and X2 are not necessarily
% equal. The requirment on their dimensions depends on the callback
% function f.
% - For efficiency, the function would invoke f to evaluate in batch.
% Thus f should support batch-evaluation. When the input arguments
% to f have n columns, f should return an 1 x n row vector.
%
% $ History $
% - Created by Dahua Lin on Apr 21, 2006
% - Modified by Dahua Lin on Sep 10, 2006
% - make some minor changes to suppress warnings
%
%% parse and verify input arguments
if nargin < 3
raise_lackinput('slpweval', 3);
end
[d1, n1] = size(X1);
[d2, n2] = size(X2);
slignorevars(d1, d2);
%% compute
% prepare output matrix
M = zeros(n1, n2);
if n1 > n2 % expand each column in X2 to n1 copies
inds_e = ones(1, n1);
for i = 1 : n2
x2 = X2(:, i);
X2e = x2(:, inds_e);
M(:, i) = feval(f, X1, X2e, varargin{:})';
end
else % expand each column in X1 to n2 copies
inds_e = ones(1, n2);
for i = 1 : n1
x1 = X1(:, i);
X1e = x1(:, inds_e);
M(i, :) = feval(f, X1e, X2, varargin{:});
end
end