2
votes

When indexing into a vector with a matrix of variable dimensions, how do I indicate to octave that the index is a matrix and not a vector?

For example, in the following code, on the fourth iteration, Octave sees the index as a row-vector and it transposes the return value of the indexing operation to be a column vector (to match the vector being indexed into rather than the one used for indexing).

When I run:

v = rand(16,1);

t = magic(4);

f = @(m)(sum(m, 1));

for i = 4:-1:1
    s = t(1:i,:);
    f(v(s))
endfor

I get:

ans =

   1.47780   2.28879   1.29786   2.98981

ans =

   1.24705   1.31940   0.87484   2.18276

ans =

   0.89387   0.55288   0.50312   1.61950

ans =  1.9294

See that on the first three iterations, the answer is a row-vector, but on the last iteration, the answer is a singleton value.

How do I tell octave that the variable s is supposed to be a matrix, not a vector and that the result of the indexing operation should always be the same shape as s?

2
I tagged this question matlab because I believe the same problem exists in Matlab as well – dspyz

2 Answers

1
votes

One way to work around this "feature" would be something like this:

v = rand(16,1);
t = magic(4);
f = @(m)(sum(m, 1));

for i = 4:-1:1
    w(1:i,:) = v(t(1:i,:));
    f(w(1:i,:))
end

This forces the output of v to be stored in w in the proper orientation. Note that I pass w(1:i,:) into the function f rather than just w because of your reverse-indexed for loop.

This is a surprising common pattern and is a useful way of repeatedly setting the columns of a matrix equal to a row vector or the rows of a matrix equal to a column vector without needing to perform a transpose or even know the orientation of the vector (who knows the the Matlab/Octave JITs do under the hood).

0
votes

How do I tell octave that the variable s is supposed to be a matrix, not a vector

In Matlab/Octave matrix and vector is the same thing. Vector is just a 1xm or mx1 matrix.

In sum function dimension option only works if both dimensions are bigger than 1.

Just make vector a special case.

for i = 4:-1:1
    s = t(1:i,:);
    if i~=1
        f(v(s))
    else
        v(s)'
    end
end