Is there a Matlab conditional IF operator that can be placed INLINE like VBA's IIF - matlab

In VBA I can do the following:
A = B + IIF(C>0, C, 0)
so that if C>0 I get A=B+C and C<=0 I get A=B
Is there an operator or function that will let me do these conditionals inline in MATLAB code?

How about simply using the fact that MATLAB automatically converts variable types when required by the operation? E.g., logical to double.
If your variables are scalar double, your code, I believe, can be replaced by
a = b + (c > 0) * c;
In this case, the operator (c > 0) values 1 (logical type) whenever c > 0 and values to 0 otherwise.

There is no ternary operator in Matlab. You can, of course, write a function that would do it. For example, the following function works as iif with n-d input for the condition, and with numbers and cells for the outcomes a and b:
function out = iif(cond,a,b)
%IIF implements a ternary operator
% pre-assign out
out = repmat(b,size(cond));
out(cond) = a;
For a more advanced solution, there's a way to create an inline function that can even do elseif, as outlined in this blog post about anonymous function shenanigans:
iif = #(varargin) varargin{2*find([varargin{1:2:end}], 1, 'first')}();
You use this function as
iif(condition_1,value_1,...,true,value_final)
where you replace the dots with any number of additional condition/value pairs.
The way this works is that it picks among the values the first one whose condition is true. 2*find(),1,'first') provides the index into the value arguments.

There is no built-in solution for this, but you can write an IIF yourself.
function result=iif(cond, t, f)
%IIF - Conditional function that returns T or F, depending of condition COND
%
% Detailed
% Conditional matrix or scalar double function that returns a matrix
% of same size than COND, with T or F depending of COND boolean evaluation
% if T or/and F has the same dimensions than COND, it uses the corresponding
% element in the assignment
% if COND is scalar, returns T or F in according with COND evaluation,
% even if T or F is matrices like char array.
%
% Syntax
% Result = iif(COND, T, F)
% COND - Matrix or scalar condition
% T - expression if COND is true
% F - expression if COND is false
% Result - Matrix or scalar of same dimensions than COND, containing
% T if COND element is true or F if COND element is false.
%
if isscalar(cond)
if cond
result = t;
else
result = f;
end
else
result = (cond).*t + (~cond).*f;
end
end

Others have said already that there is no ternary ?: operator in Matlab. As a solution I suggest this function, which takes three functions instead of values. Therefore the amount of unnecessary calculations is minimized and you can check conditions before starting calculations, e.g. if a value is really numeric, or finite, or nonzero:
function [ out ] = iif( condition, thenF, elseF, in, out)
%iif Implements the ternary ?: operator
% out = iif (#condition, #thenF, #elseF, in[, out])
%
% The result is equivalent to:
% condition(x) ? thenF(x) : elseF(x)
%
% The optional argument out serves as a template, if the output type is
% different from the input type, e.g. for mapping arrays to cells and
% vice versa.
%
% This code is in the public domain.
mask = condition(in);
if nargin <= 4
out = in;
end
if sum(mask)
out(mask) = thenF(in(mask));
end
if sum(~mask)
out(~mask) = elseF(in(~mask));
end
end
Use it like this:
f = #(y)(iif(#(x)(x > 3), #(x)(x.^2), #(x)(x/2), y))
f(linspace(0,6,10))

Inspired by Jonas' answer the function below also works for mixed type input and chars, for which his function isn't stable.
function out = iif(cond, a, b)
%IIF implements a ternary operator
% Use cell output for either char or mixed type input
if ischar(a) || ischar(b) || ~strcmp(class(a), class(b))
out = cell(size(cond));
[out{cond}] = deal(a);
[out{~cond}] = deal(b);
else
% Use array output and logical indexing
out = repmat(b, size(cond));
out(cond) = a;
end
end
Edit: weeded out the extra conditional options in the cell branch, which were apparently remnants of a previous mistake, this is probably faster, and definitely cleaner.

What you refer to is a ternary operator, in C-like notation, ?:. The expression
tern = bool ? T : F
returns T if bool evaluates to true, F otherwise. MATLAB has no ternary operator, however it can be implemented in different ways as an inline expression.
Arrays
% cell array version (any type)
tern = {F,T}{bool+1} % only Octave
tern = subsref({F,T}, struct('type', '{}', 'subs', {{bool+1}}))
% vector array version (numeric types only)
tern = [F,T](bool+1) % only Octave
tern = subsref([F,T], struct('type', '()', 'subs', {{bool+1}}))
Note that T and F have been swapped, and that different brackets are used. The vector array version is a specialization for numeric types. MATLAB does not allow direct indexation of fresh arrays, hence the use of subsref.
Pros: Works for any type and any value. Can be used inline.
Cons: Before returning the result to tern, both T and F
are evaluated.
Logical operators and eval
( bool && eval('tern=T') ) || eval('tern=F')
Note that the logical operators are short-circuited.
Pros: Works for any type and any value. Only one, T or F, is evaluated.
Cons: Works only in Octave. Can't be used inline, but through the variable tern. eval is not efficient but required.
Basic arithmetic
tern = bool*T + !bool*F
Pros: Can be used inline.
Cons: Works only for numeric types, and might fail when T or F are NaN or Inf. Both, T and F, are evaluated.
Maximum
tern = max(T,F) % bool = T>F
Note that this solution fits the particular requirements of the initial question with max(C,0).
Pros: Can be used inline.
Cons: Works only for numeric types, and might fail when T or F are NaN. Both, T and F, are evaluated. Use is strongly limited.

There is now a tern function on the MathWorks file exchange:
http://www.mathworks.com/matlabcentral/fileexchange/39735-functional-programming-constructs/content/tern.m
The code is reproduced here:
function varargout = tern(condition, true_action, false_action)
% out = tern(condition, true_action, false_action)
%
% Ternary operator. If the first input is true, it returns the second
% input. Otherwise, it returns the third input. This is useful for writing
% compact functions and especially anonymous functions. Note that, like
% many other languages, if the condition is true, not only is the false
% condition not returned, it isn't even executed. Likewise, if the
% condition is false, the true action is never executed. The second and
% third arguments can therefore be function handles or values.
%
% Example:
%
% >> tern(rand < 0.5, #() fprintf('hi\n'), pi)
% ans =
% 3.1416
% >> tern(rand < 0.5, #() fprintf('hi\n'), pi)
% hi
%
% It works with multiple outputs as well.
%
% >> [min_or_max, index] = tern(rand < 0.5, ...
% #() min([4 3 5]), ...
% #() max([4 3 5]))
% min_or_max =
% 5
% index =
% 3
%
% Tucker McClure
% Copyright 2013 The MathWorks, Inc.
if condition() % Works for either a value or function handle.
[varargout{1:nargout}] = true_action();
else
[varargout{1:nargout}] = false_action();
end
end

This is more of an addenum to Alex's answer.
Alex's method doesn't work when you want to return inf
In these cases you often end up getting a 0*inf figure, which MATLAB will evaluate to NaN. Problematic... We can avoid this multiplication using a lookup instead.
As an example, a useful barrier function in convex optimization is something that behaves like log everywhere positive, and -inf elsewhere. Here is how you might create such a function using a lookup:
INF_CONDITION = [0, inf];
fn_logbr = #(x) (x>0)*log(x) - INF_CONDITION( 1+(x<=0) )
Inline conditionals are a hack, and you lose lazy evaluation. You have to be careful. However, having semantic code is really nice, and its easier to share your code when you can't guarantee everyone's environments are the same.

If you're looking for an option that doesn't force you to build a function and can take care fairly simple expressions, you can take advantage of anonymous functions. The anonymous function returns a logical, which can be a numeral 1 or 0. Because of this, they can be used to multiply with other numbers to determine if they still hold a value after the expression, or lose their value.
For your case (including if A, B, and C are vectors or not): A = B .+ (#() C>0)()

Using:
eval('input;', 'input = 1;');
is very helpful where 'input' might not exist in the first place.

Related

Calling if else output to other script

I have written a function called "tension.m" in which I have used if else condition as shown below.
function [T,T_earlyvalues,T_latervalues] = tension(u,sigma,G,N,K)
%the values of sigma,G,N,K can be taken arbitrary.
sigma=2; G=3;N=8;K=1; v=1;
w=2.2;
if u<w
T =v*sqrt(sigma+G^2/(N-K));
T_earlyvalues=T;
else
T=(2*v)*sqrt(sigma+G^2/(N+K));
T_latervalues=T;
end
Now in another script "myvalues.m" I need to call T_earlyvalues and T_latervalues separately.
%have some coding before this part
sigma0=2400; lambda=1.3; v=2; sigma=2; G=3;N=8;K=1;
u=0:0.01:5;
T=tension(u,sigma,G,N,K);
T_earlyvalues=tension(u,sigma,G,N,K);
T_latervalues=tension(u,sigma,G,N,K);
deltaA=T_earlyvalues*sigma0*pi;
deltaB=T_latervalue*lambda*pi/2;
%have some coding after this part
How could I call the said values which are under if-else statement from tension.m function to myvalues.m script?
You have defined the tension function such that it returns three outputs.
If you call that function by requiring only one output, the function returns the first value, in your case, T
This implies that
T=tension(u,sigma,G,N,K);
shoud work since T is the first output parameter
T_earlyvalues=tension(u,sigma,G,N,K);
T_latervalues=tension(u,sigma,G,N,K);
are not working, since, actually tension returns the first value (T, whjikle you are expecting the second and the third respectively.)
You can cahnge the two above calls this way:
[~,T_earlyvalues,~]=tension(u,sigma,G,N,K);
[~,~,T_latervalues]=tension(u,sigma,G,N,K);
The ~ allows to avoid the function return the output paraemter.
You can find additional information here
Notice that in your function T_earlyvalue is not set in the else block, same for T_latervalue in the if block.
This will generate an error such as
Output argument T_earlyvalue (and maybe others) not assigned during call to tension
or
Output argument T_latervalues (and maybe others) not assigned during call to tension
You can initialize the output values to default values, at the beginning of the function, for example:
T=NaN
T_earlyvalue=NaN
T_latervalues=NaN
You can then use these special values (or any other you want to use) to trace, for example, if the if block has been executed or the else.
There seem to be a number of issues here, not the least of which is some confusion about how output argument lists work when defining or calling functions. I suggest starting with this documentation to better understand how to create and call functions. However, this issue is somewhat moot because the larger problem is how you are using your conditional statement...
You are trying to pass a vector u to your function tension, and from what I can tell you want to return a vector T, where the values of T for u < w are computed with a different formula than the values of T for u >= w. Your conditional statement will not accomplish this for you. Instead, you will want to use logical indexing to write your function like so:
function [T, index] = tension(u, sigma, G, N, K)
T = zeros(size(u)); % Initialize T to a vector of zeroes
w = 2.2;
index = (u < w); % A logical vector, with true where u < w, false where u >= w
T(index) = u(index)*v*sqrt(sigma+G^2/(N-K)); % Formula for u < w
T(~index) = 2*(u(~index)-v)*sqrt(sigma+G^2/(N+K)); % Formula for u >= w
end
Now you can call this function, capturing the second output argument to use for identifying "early" versus "late" values:
sigma0 = 2400; lambda = 1.3; v = 2; sigma = 2; G = 3; N = 8; K = 1;
u = 0:0.01:5;
[T, earlyIndex] = tension(u, sigma, G, N, K); % Call function
T_earlyvalues = T(earlyIndex); % Use logical index to get early T values
T_latervalues = T(~earlyIndex); % Use negated logical index to get later T values
And you can then use the subvectors T_earlyvalues and T_latervalues however you like.

Understanding Non-homogeneous Poisson Process Matlab code

I have found the following Matlab code to simulate a Non-homogeneous Poisson Process
function x = nonhomopp(intens,T)
% example of generating a
% nonhomogeneousl poisson process on [0,T] with intensity function intens
x = 0:.1:T;
m = eval([intens 'x']);
m2 = max(m); % generate homogeneouos poisson process
u = rand(1,ceil(1.5*T*m2));
y = cumsum(-(1/m2)*log(u)); %points of homogeneous pp
y = y(y<T); n=length(y); % select those points less than T
m = eval([intens 'y']); % evaluates intensity function
y = y(rand(1,n)<m/m2); % filter out some points
hist(y,10)
% then run
% t = 7 + nonhomopp('100-10*',5)
I am new to Matlab and having trouble understanding how this works. I have read the Mathworks pages on all of these functions and am confused in four places:
1) Why is the function defined as x and then the intervals also called x? Like is this an abuse of notation?
2) How does the square brackets affect eval,
eval([intens 'x'])
and why is x in single quotations?
3) Why do they use cumsum instead of sum?
4) The given intensity function is \lambda (t) = 100 - 10*(t-7) with 7 \leq t \leq 12 How does t = 7 + nonhomopp('100-10*',5) represent this?
Sorry if this is so much, thank you!
To answer 2). That's a unnecessary complicated piece of code. To understand it, evaluate only the squared brackets and it's content. It results in the string 100-10*x which is then evaluated. Here is a version without eval, using an anonymous function instead. This is how it should have been implemented.
function x = nonhomopp(intens,T)
% example of generating a
% nonhomogeneousl poisson process on [0,T] with intensity function intens
x = 0:.1:T;
m = intens(x);
m2 = max(m); % generate homogeneouos poisson process
u = rand(1,ceil(1.5*T*m2));
y = cumsum(-(1/m2)*log(u)); %points of homogeneous pp
y = y(y<T); n=length(y); % select those points less than T
m = intens(y); % evaluates intensity function
y = y(rand(1,n)<m/m2); % filter out some points
hist(y,10)
Which can be called like this
t = 7 + honhomopp(#(x)(100-10*x),5)
the function is not defined as x: x is just the output variable. In Matlab functions are declared as function [output variable(s)] = <function name>(input variables). If the function has only one output, the square brackets can be omitted (like in your case). The brackets around the input arguments are, as instead, mandatory, no matter how many input arguments there are. It is also good practice to end the body of a function with end, just like you do with loops and if/else.
eval works with a string as input and the square brackets apprently are concatenating the string 'intens' with the string 'x'. x is in quotes because, again, eval works with input in string format even if it's referring to variables.
cumsum and sum act differently. sum returns a scalar that is the sum of all the elements of the array whereas cumsum returns another array which contains the cumulative sum. If our array is [1:5], sum([1:5]) will return 15 because it's 1+2+3+4+5. As instead cumsum([1:5]) will return [1 3 6 10 15], where every element of the output array is the sum of the previous elements (itself included) from the input array.
what the command t = 7 + nonhomopp('100-10*',5) returns is simply the value of time t and not the value of lambda, indeed by looking at t the minimum value is 7 and the maximum value is 12. The Poisson distribution itself is returned via the histogram.

Symbolic diff in matlab should return vector

If I have a symbolic function p(r,s) = r^3 in MATLAB, I obtain the derivatives dp/dr = 3r^2 and dp/ds = 0, but my goal is to use matlabFunction to convert these expressions to function handles, with vector inputs (r,s). I want something similar to zeros(size(s)), for the derivative dp/ds so I don't obtain a scalar output if my input (r,s) is a vector.
This code I tried:
syms r s
p = r^3
dpds = diff(p,s)
gives a scalar zero not variable size zero, i.e scalar output if we have vector input.
This is the nature of how matlabFunction works. If you provide an equation that has no independent variables as part of the equation, it will default to giving you an anonymous function with no inputs and give you a scalar result.
For example:
>> syms r s;
>> p = r^3;
>> dpds = diff(p,s);
>> dpdsFunc = matlabFunction(dpds)
dpdsFunc =
#()0.0
This will only give you a single scalar value each time. This also applies to any scalar function that gives a non-zero output. If you'd like to override this behaviour and give a variable length of this scalar that is dependent on the length of the input, you can first detect if there are any input variables in the function by checking how many variables there are. You can use symvar for that. You would check if this array has a length of 0, and if it does, you override the function.
Something like this comes to mind:
syms r s;
p = r^3;
dpds = diff(p,s);
if numel(symvar(dpds)) == 0
dpdsFunc = #(s) ones(size(s))*double(dpds); %// Thanks Daniel!
else
dpdsFunc = matlabFunction(dpds);
end
This should achieve what you want.
Minor Note
I actually think this variable length of zeroes business is something that should be put into MATLAB by default, rather than defaulting to a single value. It makes vectorizing code a lot easier. I'm tempted to submit a feature request to MathWorks in the future.

MATLAB: Cannot properly evaluate function using input vector

I am trying to pass a vector into a function, and evaluate the vector over a piecewise function. When I run the code below, I am only returned a single number rather than a vector. Any ideas?
Thanks!
t[-5:1:50]
velocity(t)
function [v] = velocity( t )
%This function takes vector 't' and evaluates a velocity over a given
%piecewise function
if t>=0 & t<=8
v=10*t^2-5*t;
elseif t>=8 & t<=16
v=624-5*t;
elseif t>=16 & t<=26
v= 36*t+12*(t-16)^2;
elseif t>26
v=2136*exp(-0.1*(t-26));
else t<0
end
When you elevate a vector to the square, you are performing a scalar product with itself.
Replace t^2 with t.^2 for element-wise operators.
Do the same for (t-16).^2.
All the other operators should fall automatically into the element wise case but you can add points before them to be sure.
And, furthermore, the conditions as you have wrote them apply to a t as a scalar value. You can get the researched effect by doing the following:
Instead of
if cond1:
v = something
elif cond2:
v = something_else
Do
indices1 = (cond1) % where cond1 is t < 10 for example
indices2 = (cond2) % and cond2 is t >= 10
v[indices1] = something
v[indices2] = something_else
I hope you get the gist.

Bitwise commands such as Bitor with many inputs?

Matlab takes only two inputs with bitwise commands such as bitor. bitor(1,2) returns 3 and bitor(1,2,4) does not return 7 but:
ASSUMEDTYPE must be an integer type name.
Currently, I create for-loops to basically create a bitwise command to take as many inputs as needed. I feel the for-loops for this kind of thing is reinvention of the wheel.
Is there some easy way of creating the bitwise operations with many inputs?
Currently an example with some random numbers, must return 127
indices=[1,23,45,7,89,100];
indicesOR=0;
for term=1:length(indices)
indicesOR=bitor(indicesOR,indices(term));
end
If you don't mind getting strings involved (may be slow):
indicesOR = bin2dec(char(double(any(dec2bin(indices)-'0'))+'0'));
This uses dec2bin to convert to strings of '0' and '1'; converts to numbers 0 and 1 by subtracting '0'; applys an "or" operation column-wise using any; and then converts back.
For AND (instead of OR): replace any by all:
indicesAND = bin2dec(char(double(all(dec2bin(indices)-'0'))+'0'));
For XOR: use rem(sum(...),2):
indicesXOR = bin2dec(char(double(rem(sum(dec2bin(indices)-'0'),2))+'0'))
EDIT: I just found out about functions de2bi and bi2de (Communications Toolbox), which avoid using strings. However, they seem to be slower!
indicesOR = bi2de(double(any(de2bi(indices))));
indicesAND = bi2de(double(all(de2bi(indices))));
indicesXOR = bi2de(double(rem(sum((de2bi(indices))));
Another approach is to define a recursive function, exploiting the fact that AND, OR, XOR operations are (bit-wise) associative, that is, x OR y OR z equals (x OR y) OR z. The operation to be applied is passed as a function handle.
function r = bafun(v, f)
%BAFUN Binary Associative Function
% r = BAFUN(v,f)
% v is a vector with at least two elements
% f is a handle to a function that operates on two numbers
if numel(v) > 2
r = bafun([f(v(1), v(2)) v(3:end)], f);
else
r = f(v(1), v(2));
end
Example:
>> bafun([1,23,45,7,89,100], #bitor)
ans =
127