Question

I have to write a Matlab script that does this:

The input is 2 matrices, A(m x n) and D(m x 1). The output is a matrix, C (m x n). C is calculated like this:

function c = scanrow(a,d)
[rows columns] = size(d);
for i=1:columns
a(i,:) = a(i,:).*d(i);   
end
c = a;
end

The requirement is not using recursion. I have no idea to solve this problem. Glad that you can help. Thank you.

Was it helpful?

Solution

If the problem is "multiply every element in each row of A with the corresponding element on the corresponding row of D" then I would suggest the following:

dd = repmat(d, 1, size(a, 2))
c = a.*dd

Example:

>> a = [1 2; 3 4; 5 6];
>> d = [1 2 3]';
>> dd = dd = repmat(d, 1, size(a, 2))
dd = 
     1   1
     2   2
     3   3
>> a.*dd
ans =
     1   2
     6   8
     15  18

OTHER TIPS

Just as an FYI - bsxfun + function handles is the new hotness for performing operations on matrices and vectors where at least one matrix dimension matches one vector dimension. This avoids explicit rempat's which can be slow and wasteful:

a = 1:5;
b = magic(5);

c = bsxfun(@times,a,b);

But be careful - this is only available in relatively newer MATLAB versions. -pete

(I'll answer, despite the fact that this is homework. I think that many do not appreciate why bsxfun was created.)

There are other solutions by the way to the multiplication. The typical ones would be to use repmat, to use a loop, or to multiply by a diagonal matrix. Better is if the diagonal matrix is made to be a sparse matrix. However, bsxfun is definitely the correct solution. It was written to solve problems like this. The issue is that when you do things like

A = magic(3) + 5

MATLAB understands that it must add 5 to every element of magic(3). Likewise, when you do

A = magic(4).*2

again, MATLAB understands that the multiplication is to be extended across all elements. In essence, MATLAB implicitly expands the scalar into an array of the same size as its partner in the addition or multiplication, and then performs the operation. This is what was done explicitly by the repmat solver.

The problem with an explicit scalar expansion is that this takes time and memory to do that expansion. So times and plus are smart enough to recognize that scalar expansion is appropriate, but not actually do the explicit memory hogging operation. MATLAB does not know what to do when you try

A = magic(3).*rand(1,3)

In the past, the solution was to use repmat. But, when you use repmat to do an explicit expansion of a vector into a matrix, you eat up a lot of memory to solve a problem in a vectorized way. Yes, it is common for vectorizations to trade memory for time in MATLAB, but this may be a bad thing if you are already memory limited, and you are working on a big problem. Forcing MATLAB (and your OS) to move into virtual memory is a very bad idea when it is not necessary. (Any solution is acceptable for a tiny problem.)

So when you try to multiply an array like magic(3) by a row or a column vector, should MATLAB understand that it should do an implicit expansion of the vector into an array? Or should MATLAB assume that you have made an error, and flag this as such? This problem, known as expansion of singleton dimensions is the issue. (A singleton dimension is found in a vector, where one of the dimensions was 1.) Returning an error message is a good idea for many users, since often this signals that a bug has been found, a mistake made. Simple, automatic expansion of all singleton dimensions to fit the problem at hand would seem to be dangerous. In fact, there were many discussions about what to do. For example, should MATLAB create a preference, where the user could enable expansion of singleton dimensions in their version of MATLAB? This would be a poor idea, since it would make code non-portable across systems.

Also if the basic MATLAB operators were modified to always expand all singleton dimensions, then MATLAB code would be strongly non-portable back to older releases.

We even discussed creating an entire new set of MATLAB operators, like .* exists in parallel to *, to do an operation while expanding singleton dimensions. This too was a poor idea, and rightly avoided.

The solution was to create BSXFUN (Binary Scalar eXpansion FUNction) to allow this operation to be done efficiently when it is desired. There is a bsxfun found on the file exchange that allows users of older releases to gain this behavior, so portability is maintained as well as possible. BSXFUN allows you to operate on any pair of arguments, applying a user supplied function between them. So it allows you to do things like this:

A = rand(5,1);
B = rand(1,3);
C = bsxfun(@plus,A,B);

to create a 5x3 matrix of the sum of the elements in each of A and B. You can use any function as the first operand too, so BSXFUN is very powerful.

Finally, another way to look at BSXFUN is as a variation of an outer product. Thus, this operation in MATLAB is perfectly well defined:

A = rand(5,1);
B = rand(1,3);
C = A*B;

However, either of these operations

D = A-B;
E = A^B;

will generate an error. BSXFUN allows you to do them efficiently with no memory hogging singleton dimension expansions.

D = bsxfun(@minus,A,B);
E = bsxfun(@power,A,B);

Maybe vectorize() is what you want -> Code Vectorization Guide

Are you certain that the code you included in the question is correct? This is what it appears to do:

I assume the inputs a and d represent the matrices A (size m-by-n) and D (size m-by-1) that you mentioned. Since you defined d as always having 1 column, then the for loop is unnecessary since it will only loop once. The single pass through the loop will simply multiply the values in the first row of a by the first value in d. The entire piece of code in the question can therefore be replaced with the following:

c = a;
c(1,:) = c(1,:).*d(1);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top