bsxfun is your friend:
out = bsxfun(@rdivide, d, norms);
What this does is that it temporarily creates a 3D matrix that replicates each row of norms for as many columns as there are in d and it divides each element in an element-wise manner with d and norms.
We get:
>> d = cat(3, [1 2 3; 4 5 6], [7 8 9; 10 11 12]);
>> norms = sqrt(sum(d.^2,2));
>> out = bsxfun(@rdivide, d, norms)
out(:,:,1) =
0.2673 0.5345 0.8018
0.4558 0.5698 0.6838
out(:,:,2) =
0.5026 0.5744 0.6462
0.5234 0.5758 0.6281
We can also verify that each row is L2-normalized by determining the sum of squares along each row independently and ensuring that each result sums to 1:
>> sum(out.^2, 2)
ans(:,:,1) =
1.0000
1.0000
ans(:,:,2) =
1.0000
1.0000
If the approach with bsxfun doesn't quite make sense, an alternative you could use is to create a matrix that respects the same dimensions as d by using repmat... then you can perform the element-wise division you desire:
>> out = d ./ repmat(norms, [1 size(d,2) 1])
out(:,:,1) =
0.2673 0.5345 0.8018
0.4558 0.5698 0.6838
out(:,:,2) =
0.5026 0.5744 0.6462
0.5234 0.5758 0.6281
With repmat you specify how many times you want the matrix to be copied in each dimension. We only want the matrix to be replicated over the columns while the number of rows and slices are the same... hence the vector [1 size(d,2) 1] that specifies how many times you want the matrix copied in each dimension.
Actually, this is what bsxfun does under the hood without you having to deal with the headaches of creating this temporary matrix. This replication is done for you without having you think about it.