2

I see equivalent operations being done several times in my Matlab code, and I think, there must be a way to condense these and do it all once. In this case it was checking whether some variables were less than a certain epsilon:

if abs(beta) < tol
    beta = 0;
end
if abs(alpha) < tol
    alpha = 0;
end
if abs(gamma) < tol
    gamma = 0;
end

I tried combining these into a few lines that deal with the whole boodle,

overTol = [alpha,beta,gamma] >= tol;
[alpha,beta,gamma] = [alpha,beta,gamma] .* overTol;

If this was Python, where a list is a list is a list, that would be fine, but in Matlab, an operation on the right produces one variable on the left except in special situations.

After reading Define multiple variables at the same time in MATLAB? and Declare & initialize variables in one line in MATLAB without using an array or vector, I tried using deal, but [alpha,beta,gamma] = deal([alpha,beta,gamma] .* overTol); does not distribute the terms of the vector given to the deal function between the terms in the vector on the left, but instead gives a copy of the whole vector to each of the terms.

The last thing I want to do is set the right equal to a unique vector and then set alpha, beta, and gamma equal to the terms of that vector, one by one. That's just as ugly as what I started with.

Is there an elegant solution to this?

7
  • 2
    With deal you still need to explicitly repeat the operation on the right: [alpha, beta] = deal(alpha.*(abs(alpha)>=tol), beta.*(abs(beta)>=tol)); You could define an anonymous function f = @(x) x.*abs(x)>=x; and then alpha = f(alpha); beta = f(beta); gamma= f(gamma). To produce the most compact code you should collect the three variables into a single one (N-dim array or cell array). Would that be an option? Commented Nov 22, 2022 at 18:46
  • 2
    MATLAB does not split arrays into variables easily because MATLAB is designed to work with the arrays themselves, not with scalar values. There are tricks you could use, but I wouldn’t want to maintain code that uses these tricks. What is the problem with repeating a statement three times for three different variables? Commented Nov 22, 2022 at 19:00
  • 1
    See also stackoverflow.com/q/2337126/7328782 Commented Nov 22, 2022 at 19:25
  • 1
    @Post169 What operations do you anticipate running your values through? In this case you've reduced your 3 if clauses to alpha_beta_gamma(abs(alpha_beta_gamma)<tol) = 0; Commented Nov 23, 2022 at 0:09
  • 2
    @Post169 Once you have the three variables in an array, that should make it easier to apply any common operation to all of them... What operations are thinking of? Can you give a specific example? Commented Nov 23, 2022 at 1:15

2 Answers 2

0

Ok, the comments explain why there are probably better approaches. I was curious if it could be done. It can, but maybe it shouldn't be.

% Initial values
a = 0.01; b = 0.1; c = 1; 
% Tolerance
tol = 0.05;
% Function - note returns a scalar cell
f = @(f) {f.*(abs(f)>tol)}
% arrayfun returns a cell of the new values
% cell2struct turns that into a struct array with a single field 'f'
% the trailing dot-reference extracts that field and builds a 
% comma-separated list which can be used to assign the new values
[a2,b2,c2] =  cell2struct(arrayfun(f, [a,b,c]),{'f'}).f
Sign up to request clarification or add additional context in comments.

Comments

0

You could use cellfun to generate a cell array of results, and deal to redistribute it back into variables

f = @(x) x.*(abs(x)>tol);             % function which returns x, or x if abs(x)<tol
d = cellfun( f, {a,b,c}, 'uni', 0 );  % apply function to inputs a,b,c
[a,b,c] = deal(d{:});                 % deal results back to a,b,c

A more readable (and maintenance-friendly) method might be to just use functions and accept that it's going to use more lines. Line count is not the enemy...

a = applyTol(a);
b = applyTol(b);
c = applyTol(c);

function x = applyTol( x )
    tol = 0.5;
    if abs(x) < tol
        x = 0;
    end
end 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.