I'm struggling to vectorise a function which performs a somewhat pairwise difference between two vectors x = 2xN and v = 2xM, for some arbitrary N, M. I have this to work when N = 1, although, I would like to vectorise this function to apply to inputs with N arbitrary.
Indeed, what I want this function to do is for each column of x find the normed difference between x(:,column) (a 2x1) and v (a 2xM).
A similar post is this, although I haven't been able to generalise it.
Current implementation
function mat = vecDiff(x,v)
diffVec = bsxfun(@minus, x, v);
mat = diffVec ./ vecnorm(diffVec);
Example
x =
1
1
v =
1 3 5
2 4 6
----
vecDiff(x,v) =
0 -0.5547 -0.6247
-1.0000 -0.8321 -0.7809
CodePudding user response:
Your approach can be adapted as follows to suit your needs:
- Permute the dimensions of either
x
orv
so that its number of columns becomes the third dimension. I'm choosingv
in the code below. - This lets you exploit implicit expansion (or equivalently
bsxfun
) to compute a2
×M
×N
array of differences, whereM
andN
are the numbers of columns ofx
andv
. - Compute the vector-wise (2-)norm along the first dimension and use implicit expansion again to normalize this array:
x = [1 4 2 -1; 1 5 3 -2];
v = [1 3 5; 2 4 6];
diffVec = x - permute(v, [1 3 2]);
diffVec = diffVec./vecnorm(diffVec, 2, 1);
You may need to apply permute
differently if you want the dimensions of the output in another order.
CodePudding user response:
Suppose your two input matrices are A (a 2 x N matrix) and B (a 2 x M matrix), where each column represents a different observation (note that this is not the traditional way to represent data).
Note that the output will be of the size N x M x 2.
out = zeros(N, M, 2);
We can find the distance between them using the builtin function pdist2
.
dists = pdist2(A.', B.');
(with the transpositions required for the orientation of the matrices)
To get the individual x and y distances, the easiest way I can think of is using repmat:
xdists = repmat(A(1,:).', 1, M) - repmat(B(1,:), N, 1);
ydists = repmat(A(2,:).', 1, M) - repmat(B(2,:), N, 1);
And we can then normalise this by the distances found earlier:
out(:,:,1) = xdists./dists;
out(:,:,2) = ydists./dists;
This returns a matrix out
where the elements at position (i, j, :)
are the components of the normed distance between A(:,i)
and B(:,j)
.