function out = vif(truth,yes,no)
% VIF(TRUTH, YES, NO) is a function interface for simple vectorised if-else
% statements. It returns a value with the same shape as TRUTH, with values
% taken from YES or NO, depending upon whether the corresponding element of
% TRUTH is true or false. YES and NO must be scalars or matrices with the
% same shape as TRUTH.
% Example:
% vif(eye(3), 4, 1+1i)
% ans =
%
% 4.0000 1.0000 + 1.0000i 1.0000 + 1.0000i
% 1.0000 + 1.0000i 4.0000 1.0000 + 1.0000i
% 1.0000 + 1.0000i 1.0000 + 1.0000i 4.0000
%
% vif(eye(3), rand(3), magic(3))
% ans =
%
% 0.4218 1.0000 6.0000
% 3.0000 0.6557 7.0000
% 4.0000 9.0000 0.6787
%
% vif is often faster than looped if-else
% tic; for i=1:1000000; if 1; 4; else 1+i; end; end; toc
% Elapsed time is 0.831261 seconds.
%
% truth = rand(1000000,1)< 0.5;
% tic; vif(truth, 4, 1+i); toc
% Elapsed time is 0.097463 seconds.
%
% ...but slower for the all-scalar case
% tic; for(i=1:100000); vif(1, 4, 1+i); end; toc
% Elapsed time is 12.750187 seconds.
%
% $ Author: Richard Cotton $ $ Date: 2008/10/01 $ $ Version 1.4 $
% Basic error checking of inputs
if nargin ~= 3
error('vif:wrongNumberOfInputs', 'This function requires 3 inputs.');
end
% validateattributes gives nice error messages but is slow.
% validateattributes(truth, 'logical', {}, 'vif', 'Truth')
% oktypes = {'numeric', 'logical', 'char'};
% validateattributes(yes, oktypes, {}, 'vif', 'Yes')
% validateattributes(no, oktypes, {}, 'vif', 'No')
function checktypes(x)
if ~isnumeric(x) && ~islogical(x) && ~ischar(x)
error('vif:badType', 'All inputs must be numeric, logical or char.');
end
end
checktypes(truth);
checktypes(yes);
checktypes(no);
isscalaryes = isscalar(yes);
isscalarno = isscalar(no);
sizetruth = size(truth);
if (~isscalaryes && ~isequal(size(yes), sizetruth)) || ...
(~isscalarno && ~isequal(size(no), sizetruth))
error('vif:badYesNoValue', ...
'Yes and No must be scalars or the same size as Truth.');
end
% Coerce real numeric 'truth' to logical if necessary
if isreal(truth)
truth = ~~truth; % quicker than logical(truth) for large matrices
else
truth = ~~real(truth);
warning('vif:complexTruth', ...
'Truth is complex - only the real part will be used.');
end
if ~ischar(yes) && ~ischar(no) && ...
all(isfinite(yes(:))) && all(isfinite(no(:)))
out = truth.*yes + ~truth.*no;
else
if isscalaryes
out = yes*ones(sizetruth);
else
out = yes;
end
if isscalarno
out(~truth) = no;
else
out(~truth) = no(~truth);
end
end
end