One-liner for if then [duplicate] - matlab

This question already has answers here:
ternary operator in matlab
(12 answers)
Closed 8 years ago.
Is there a one-liner in MATLAB for this?
if a > b
foo = 'r';
else
foo = 'g';
end

There is no syntactic sugar for one-line if-statements in MatLab, but if your statement is really simple you could write it in one line.
I used to have one-line if-statements like that in my old project:
if (k < 1); k = 1; end;
In your case it'll look something like:
if a > b; foo = 'r'; else; foo = 'g'; end;
or, if you don't like semicolons
if a > b, foo = 'r'; else, foo = 'g'; end
Not as pretty as you may have expected, though.

Not as elegant as a C style ternary operator but you can take advantage of the fact that matlab will automatically cast logicals into doubles in this situation. So you can just multiply your desired result for true (r in this case) by your condition (a > b), and add that to the product of your desired result for false (i.e. g) with the not of your condition:
foo = (a > b)*c + (~(a > b))*d
so if we let c = 'r' and d = 'g' then all we need to do is cast foo back to a char at the end:
char(foo)
or
char((a > b)*'r' + ~(a > b)*'g')
Note that this will only work if c and d have the same dimensions (because of the +)...

Try to avoid using if statements in matlab, and just convert your logic to (vector) math:
foo = 1 + (a <= b)
Edit:
For the more general case, of assigning 'r' or 'g', you can use:
col = {'r', 'g'};
foo = col(1 + (a > b));
So for example with an isGreen boolean you could do:
foo = col(1 + isGreen);
This could also be a boolean returning function
foo = col(1 + isGreen(a))

Related

Difference between "||" and "or" in system verilog [duplicate]

This question already has answers here:
Verilog - what is the difference in use between vertical bar (|) and "or"
(2 answers)
Closed 6 months ago.
I am trying to wait for a change in 2 signals in following 2 ways.
Option 1: #(a or b)
Option 2: #(a || b)
If any change observed for any signal then I am trying to display the value as shown below.
module wait_test;
int a, b;
initial
begin
#10 a += 10;
#10 b += 10;
#10 a += 10;
#10 b += 10;
end
initial
forever
begin
#(a or b)
$display($time,"\ta = %0d,b = %0d", a, b);
end
endmodule
Result:
10 a = 10,b = 0
20 a = 10,b = 10
30 a = 20,b = 10
40 a = 20,b = 20
When I replace #(a or b) with #(a || b), I only observe 1st display with no errors. Please help me with the reason.
Result:
10 a = 10,b = 0
The or operator in this context is described in IEEE Std 1800-2017, section 9.4.2.1 Event OR operator. Whenever there is a change in either a or b, the $display statement will be executed, as you have seen.
The || operator is a simple logical OR. It will first evaluate the expression (a || b), then the event control # syntax will wait for a change in the expression, not the individual signals. At time 0, both signals are 0, which means the expression is 0. At time 10, a changes to 10, which means the expression changes to 1. Although the signals continue to change every 10 time units, the expression remains 1, so there are no further changes in the expression.
#(a || b) is not a typical construct. #(a or b) is a typical construct.
Also, your initial forever block is much more commonly coded as:
always #* begin
$display($time,"\ta = %0d,b = %0d", a, b);
end

How to add, subtract, etc. two structs element-by-element when they have the same fields

I have various structs with fields W, P, E, which contain numerical values. I want to develop a clean way to add and subtract these structs without unpacking and repacking in subfunctions each time (which has been my solution thus far)
For example, given:
S.W = 2
S.P = 3
S.E = 4
M.W = 20
M.P = 30
M.E = 40
I want to be able to do X = S + M and end up with:
X.W = 22
X.P = 33
X.E = 44
My current attempt to do this, is by means of a new class, which looks as follows:
classdef CV
properties
W
P
E
end
methods
function r = plus(o1,o2)
r = CV;
r.E = o1.E + o2.E;
r.P = o1.P + o2.P;
r.W = o1.W + o2.W;
end
end
end
This allows for doing S + M and returns a new variable in the same form as the inputs. I'm generally unfamiliar with classes, and wanted to know if this is proper form. If so, I might go ahead and add functions for minus and times in the methods section. However, this seems like it requires a lot of repetitive code and I feel there must be a simpler solution. Any advice is much appreciated.
The following code directly works on structs without nesting them in a class. It is assumed that the two input structs have the same field names (in this example W, P, and E), however, the order of those may be arbitrary (you mentioned in a comment that this is important for your application).
function X = structplus(S, M)
fn = fieldnames(S);
for i = 1 : numel(fn)
X.(fn{i}) = M.(fn{i}) + S.(fn{i});
end
end
So defining
S.W = 2
S.P = 3
S.E = 4
M.E = 40
M.P = 30
M.W = 20
(note the reverse order of M) and calling
X = structplus(S, M)
yields a struct with field names that are ordered like the first argument:
X =
struct with fields:
W: 22
P: 33
E: 44
To expand on Le Phlaux's answer, you can provide a function handle to the required binary operator (e.g. #plus, #minus) and work on sub-structures recursively
function out = structBinaryFunc(in1, in2, func)
fn = fieldnames(in1);
for ii = 1:numel(fn)
if isstruct(in1.(fn{ii}))
out.(fn{ii}) = structBinaryFunc(in1.(fn{ii}), in2.(fn{ii}), func)
else
out.(fn{ii}) = func(in1.(fn{ii}), in2.(fn{ii}));
end
end
For your example you would call X = structBinaryFunc(S, M, #plus);.

How can one clear all the variables but the ones wanted [duplicate]

This question already has answers here:
How to declare variables immune to clear all?
(3 answers)
Closed 7 years ago.
Often when running long memory expensive programs I want to clear everything but some specific variables. If one wants to delete just some variables clear varA varB can be used, but what about deleting all but this specific variables?
As mentioned above, clearvars includes a syntax for keeping variables in the workspace while clearing the remainder:
a = 1; b = 1; c = 1; d = 1;
keepvars = {'c', 'd'};
clearvars('-except', keepvars{:});
Which functions as expected.
Like clear, it can also accommodate regexp matching:
a1 = 1; a2 = 1; b = 1; c = 1;
keepvars = 'a\d'; % regex pattern
clearvars('-except', '-regexp', keepvars);
Which retains a1 and a2, as expected.
Make use of the fact that both who and whos have return values that can be stored in variables. The former returns a cell array of strings, the latter a struct array. For what you need, the former will suffice:
%// don't delete these '
keepvars = {'varA','varB'};
%// delete these
delvars = setdiff(who,keepvars);
clear(delvars{:},'delvars');

Text formating - write out words following XY

I am fairly new to MATLAB and for my homework I have a block of text from which I need to select words after "and" or "And" and then replace every letter X for letter Y. I know how to do this in python through .split() and cycling through a sting(word) where I search for X. However, in matlab I am lost. Could you please tell me if there are some equivalent commands ? Something along the commands like
fileread
textscan
fseek
Thank you
EDIT:
What I actaully meant was that from a string:
str = 'I like apples and pineapples and other fruit'
I need to obtain
'pineapples'
'other'
and return these with 'e' switched for 'z'
Use regular case-insensitive regular expressions. Find everything after and or And, and switch X with Y:
str = 'This is a text with X and X and Z'
[startIndex,endIndex] = regexpi(str,'and');
str2 = str(endIndex(1) + 1 : end)
str2(str2 == 'X') = 'Y';
str = [str(1:endIndex), str2]
str =
This is a text with X and Y and Z
It is a bit messy. I guess it could be done simpler, but at least it works! If you don't case about the case of X, use strcmpi instead of ==.
UPDATE#:
After your comment, I guess this should work:
[startIndex,endIndex] = regexpi(str,'and');
str2 = str(endIndex(1) + 1 : end);
words = regexp(str2,' ','split');
nums = cellfun(#(x) find(x == 'e'), words, 'UniformOutput', false);
[idx] = find(~cellfun(#isempty, nums));
wordList = words(idx)
wordList(wordList == 'e') = 'X'

What are # and : used for in Qbasic?

I have a legacy code doing math calculations. It is reportedly written in QBasic, and runs under VB6 successfully. I plan to write the code into a newer language/platform. For which I must first work backwards and come up with a detailed algorithm from existing code.
The problem is I can't understand syntax of few lines:
Dim a(1 to 200) as Double
Dim b as Double
Dim f(1 to 200) as Double
Dim g(1 to 200) as Double
For i = 1 to N
a(i) = b: a(i+N) = c
f(i) = 1#: g(i) = 0#
f(i+N) = 0#: g(i+N) = 1#
Next i
Based on my work with VB5 like 9 years ago, I am guessing that a, f and g are Double arrays indexed from 1 to 200. However, I am completely lost about this use of # and : together inside the body of the for-loop.
: is the line continuation character, it allows you to chain multiple statements on the same line. a(i) = b: a(i+N) = c is equivalent to:
a(i)=b
a(i+N)=c
# is a type specifier. It specifies that the number it follows should be treated as a double.
I haven't programmed in QBasic for a while but I did extensively in highschool. The # symbol indicates a particular data type. It is to designate the RHS value as a floating point number with double precision (similar to saying 1.0f in C to make 1.0 a single-precision float). The colon symbol is similar to the semicolon in C, as well, where it delimits different commands. For instance:
a(i) = b: a(i+N) = c
is, in C:
a[i] = b; a[i+N] = c;