2.8. Functions of Vectors

Reading Assignment

Please read chapter 7 of Physical Modeling in MATLAB, by Allen B. Downey [DOWNEY11].

Chapter 7 of Physical Modeling in MATLAB begins by making the observation that functions may also reside in the file for another function. Like functions residing inside a script file, these helper functions are private to the file and may only be called from other functions in the file.

2.8.1. Replacing Loops with Vectorized Code

As mentioned in the For Loops and Vectors sections, MATLAB has the ability to operate on whole vectors and matrices with a single arithmetic expression. Code that takes advantage of this feature is said to be vectorized. Such code has two benefits over code that uses loops to iterate over the elements of vectors. First, it can be simpler and faster to write vectorized code than to write code using loops. Secondly, vectorized code runs faster because MATLAB’s interpreter runs less and optimized, compiled code runs more to perform the calculations.

The functions tic and toc are used below to illustrate the difference. More complex expressions yield more speed improvements for vectorized code.

% Series calculation of pi/4 (0.7849)
N = 1003;
%% For Loop Code
tic
mysum = 0;
sign = -1;
for n = 1:2:N
    sign = -sign;
    mysum = mysum + sign/n;
end
toc
disp(['For Loop Code: ', num2str(mysum)])

%% Vectorized Code 1
tic
denom1 = 1:4:N;
denom2 = 3:4:N;
mysum = sum(1./denom1) - sum(1./denom2);
toc
disp(['Vectorized Code 1: ', num2str(mysum)])

%% Vectorized Code 2
tic
n = 1:4:N;
mysum = sum(1./n - 1./(n+2));
toc
disp(['Vectorized Code 2: ', num2str(mysum)])

2.8.2. Vectors as Input Variables

Functions that you write should assume that they may be called with vectors as input variables, even if your intent is that it work with scalar inputs. Thus, unless the function is performing matrix operations, use elementwise operators.

Don’t Use Instead Use
* .*
/ ./
^ .^

2.8.3. Logical Vectors

Logical vectors are formed by testing a vector with a logical expression. The resulting vector is 1 (true) for each value in the original vector where the logical expression is true and 0 (false) in the other positions.

>> A = 1:10
A =
    1     2     3     4     5     6     7     8     9    10
>> A > 3 & A <8
ans =
  1x10 logical array
   0   0   0   1   1   1   1   0   0   0

Next we use a logical vector to modify the vector A. The mod function gives the result of modulus division (the remainder after integer division). The first expression below shows a 1 where the vector is odd and a 0 where it is even. The second expression sets A to 0 for each odd value. It does so by first creating a temporary logical vector. Then, for each element in A where the logical vector is true is given the new value of 0.

>> mod(A,2)
ans =
    1     0     1     0     1     0     1     0     1     0
>> A(mod(A,2) == 1) = 0
A =
    0     2     0     4     0     6     0     8     0    10
find

The find function takes a logical vector as input and returns a vector holding the indices where the logical vector is true.

The following example uses an integer random number generator to make the sequence of numbers.

>> A = randi(10,1,10)
A =
    8     4     6     2     7     3     7     7     8     5
>> find(A > 6)
ans =
    1     5     7     8     9
nnz

You can use the function nnz to count the number of non-zero or the number of true values in a logical array.

>> nnz(A > 6)
ans =
    5
Logical Vector Functions
Purpose Function Output
Are any of the elements true? any true/false
Are all the elements true? all true/false
How many elements are true? nnz double
What are the indices of the elements that are true? find double

2.8.4. Sinc Revisited

When we looked at the Example Control Constructs - sinc, we commented that it would be better to use vectors. Here it is with vectors. Notice the use of a logical vector.

t = linspace(-4*pi,4*pi,101);
t(t == 0) = eps;
y = sin(t)./t;
figure, plot(t, y)
hold on
plot([-4*pi 4*pi],[0 0], 'r')
xticks(linspace(-4*pi,4*pi, 9))
xticklabels({'-4\pi','-3\pi','-2\pi','-\pi','0',...
     '\pi','2\pi','3\pi','4\pi'});

% Next four lines for MATLAB 2016a and older
% ax = gca;
% ax.XLim = [-4*pi 4*pi];
% ax.XTick = linspace(-4*pi,4*pi, 9);
% ax.XTickLabel = {'-4\pi','-3\pi','-2\pi','-\pi','0',...
%     '-2\pi','\pi','3\pi','4\pi'};

title('Sinc Function')
axis tight
hold off