6

Say I have a matrix A of dimension NxV. I want to create a larger matrix of size NTxVT, i.e. I want to replace each element e of the matrix A(e) with diag(T)*A(e)., while keeping the general orientation of the matrix (for instance, A(e) is to the left of A(e-1), so diag(T)*A(e) is to the left of diag(T)*A(e-1).

Is there a trick to accomplish this in matlab? (making each diagonal matrix and concatenating them will take forever).

Many thanks ^^

2
  • 2
    Could it be you are looking for the kron command? de.mathworks.com/help/matlab/ref/kron.html Commented Mar 20, 2015 at 23:34
  • 1
    Won't you end up with a matrix of size NTn x V instead, where Tn is size(T,1) because diag(T) would be size(T,1)? Commented Mar 21, 2015 at 2:39

5 Answers 5

6
A = magic(3); T = diag([-1 1]); kron(A,T) 

gives

-8 0 -1 0 -6 0 0 8 0 1 0 6 -3 0 -5 0 -7 0 0 3 0 5 0 7 -4 0 -9 0 -2 0 0 4 0 9 0 2 

ps. I copied the idea from this example

Sign up to request clarification or add additional context in comments.

1 Comment

This is the way to go! Concise and fast.
4

Here is a solution using bsxfun

A = magic(3); T = [-1 1] T = diag(T); M=bsxfun(@times,permute(A,[3,1,4,2]),permute(T,[1,3,2,4])); M=reshape(M,size(T).*size(A)); 

It creates a 4D-Matrix where the individual blocks are M(:,i,:,j), then this is reshaped to a 2D-Matrix.

The image processing toolbox provides another solution which is very short but slow:

A = magic(3); T = [-1 1] T = diag(T); M=blockproc(A,[1 1],@(x) x.data.*T); 

And finally a implementation which generates a sparse matrix, which might be helpful for large T as your matrix will contain many zeros:

T=[-1 1]; A=magic(3); %p and q hold the positions where the first element element is stored. Check sparse(p(:),q(:),A(:)) to understand this intermediate step [p,q]=ndgrid(1:numel(T):numel(T)*size(A,1),1:numel(T):numel(T)*size(A,2)); %now p and q are extended to hold the indices for all elements tP=bsxfun(@plus,p(:),0:numel(T)-1); tQ=bsxfun(@plus,q(:),0:numel(T)-1); % tA=bsxfun(@times,A(:),T); M=sparse(tP,tQ,tA); 

When T is of size nx1 the sparse solution cuts your memory usage by a factor of roughly n/1.55.

3 Comments

I think, permute(A,[3,1,4,2]).*permute(T,[1,3,2,4]) looks clearer than its bsxfun equivalent.
@LeonidBeschastny: octave user? Matlab does not support broadcasting, bsxfun is required here.
You got me ;) I switched to octave a couple of years ago. And you're right, it won't work in MatLab without bsxfun.
3

The simplest way I can think of is to combine arrayfun and cell2mat functions:

B = cell2mat(arrayfun((@(x) T .* x), A, 'UniformOutput', false)); 

First, I transformed matrix A into a cell array of matrices T .* x where x is an element of A (a assumed that T is a matrix).

Then I used cell2mat to transform in back into a matrix.

Here is a complete example (execute online):

A = magic(3); T = diag([-1 1]); B = cell2mat(arrayfun((@(x) T .* x), A, 'UniformOutput', false)); 

resulting in:

B = -8 0 -1 0 -6 0 0 8 0 1 0 6 -3 0 -5 0 -7 0 0 3 0 5 0 7 -4 0 -9 0 -2 0 0 4 0 9 0 2 

Comments

1

Using just indexing:

A = magic(3); T = diag([-1 1]); %// example data from Daniel's answer [a1, a2] = size(A); [t1, t2] = size(T); M = A(ceil(1/t1:1/t1:a1), ceil(1/t2:1/t2:a2)).*T(repmat(1:t1,1,a1), repmat(1:t2,1,a2)); 

Comments

1

Using good old-fashioned matrix multiplication -

M = reshape(diag(T)*A(:).',[size(A,1)*size(T,1) size(A,2)]) 

Sample run -

A = magic(4) T = magic(3) M = reshape(diag(T)*A(:).',[size(A,1)*size(T,1) size(A,2)]) 

will result in -

A = 16 2 3 13 5 11 10 8 9 7 6 12 4 14 15 1 T = %// Notice that only diag(T) elements would be used to calculate M 8 1 6 3 5 7 4 9 2 M = 128 16 24 104 80 10 15 65 32 4 6 26 40 88 80 64 25 55 50 40 10 22 20 16 72 56 48 96 45 35 30 60 18 14 12 24 32 112 120 8 20 70 75 5 8 28 30 2 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.