MATLAB: Turn every element of complex matrix into another matrix

69 Views Asked by At

I have a n x n matrix consisting of complex elements. I want to substitute each element x with a new matrix [Im(x) -Re(x); Re(x) Im(x)]. Is there an easy way of doing this (preferably without using for-loops)?

3

There are 3 best solutions below

0
Luis Mendo On BEST ANSWER

Here's a way using kron. It is probably a little wasteful in terms of operations:

A = [1+5j, 2+3j, -4j; 2, -2+4j, -3-3j]; % example input
result = real(kron(A, [-1j -1; 1 -1j]));

This example gives

A =
   1.0000 + 5.0000i   2.0000 + 3.0000i   0.0000 - 4.0000i
   2.0000 + 0.0000i  -2.0000 + 4.0000i  -3.0000 - 3.0000i
result =
     5    -1     3    -2    -4     0
     1     5     2     3     0    -4
     0    -2     4     2    -3     3
     2     0    -2     4    -3    -3

The following approach is clunkier, but perhaps more efficient:

A = [1+5j, 2+3j, -4j; 2, -2+4j, -3-3j]; % example input
result = NaN(size(A)*2); % preallocate
result(1:2:end, 1:2:end) = imag(A);
result(1:2:end, 2:2:end) = -real(A);
result(2:2:end, 1:2:end) = real(A);
result(2:2:end, 2:2:end) = imag(A);

Like before, this gives

A =
   1.0000 + 5.0000i   2.0000 + 3.0000i   0.0000 - 4.0000i
   2.0000 + 0.0000i  -2.0000 + 4.0000i  -3.0000 - 3.0000i
result =
     5    -1     3    -2    -4     0
     1     5     2     3     0    -4
     0    -2     4     2    -3     3
     2     0    -2     4    -3    -3
1
John Bofarull Guix On

Let A be the input comple matrix.

Then

B=imag(A)-real(A) +1j*(real(A)+imag(A))

Then B is the sought matrix.

No for loops needed, not a single one.

I have assumed that in the question you omitted the '+' or whatever operation combining the 2nd pair.

5
Argyll On

One solution is to use a series of reshape to take advantage of its speed.

First, let's compose the new elements by recognizing that your desired final product involves interleaving the real part and imaginary part -- twice.

AA=reshape(A,1,numel(A));
R=real(AA);
I=imag(AA);
new=[reshape([I;-R], [], numel(AA)*2);reshape([R;I], [], numel(AA)*2)];

Here, I interleaved the components along the column. Interleaving along column has the pattern of reshape([...;...],[],numel(...)+numel(...)).

In new, you can see the result of interleaving in producing the desired 2-by-2 blocks. But at this point, the matrix is not arranged in the way desired. To reshape block-wise, we use Divakar's answer such as this one, and use it twice: once to reshape for the 2-by-2 blocks, another time to reshape for the correct number of rows in the final matrix.

ncols=2; % 2 because the blocks are 2-by-2
nrows=size(A,1)*2;
new=reshape(permute(reshape(new,size(new,1),ncols,[]),[1,3,2]),[],ncols);
new=reshape(permute(reshape(new',size(new,2),nrows,[]),[1,3,2]),[],nrows)';

And new will have the desired shape.

Example:

>> A=rand(2,3)+rand(2,3)*1i
A =
   0.8147 + 0.2785i   0.1270 + 0.9575i   0.6324 + 0.1576i
   0.9058 + 0.5469i   0.9134 + 0.9649i   0.0975 + 0.9706i
>> AA=reshape(A,1,numel(A));
>> I=imag(AA);
>> R=real(AA);
>> new=[reshape([I;-R], [], numel(AA)*2);reshape([R;I], [], numel(AA)*2)];
>> ncols=2;
nrows=size(A,1)*2;
new=reshape(permute(reshape(new,size(new,1),ncols,[]),[1,3,2]),[],ncols);
new=reshape(permute(reshape(new',size(new,2),nrows,[]),[1,3,2]),[],nrows)',
new =
    0.2785   -0.8147    0.9575   -0.1270    0.1576   -0.6324
    0.8147    0.2785    0.1270    0.9575    0.6324    0.1576
    0.5469   -0.9058    0.9649   -0.9134    0.9706   -0.0975
    0.9058    0.5469    0.9134    0.9649    0.0975    0.9706

The reshape and permute calls are designed to be fast in Matlab. While we cannot say with certainty what they do under the hood, they likely do not change the underlying data but change how indices from users convert to addresses for the underlying data. Instantiating this simple formula should cost next to nothing.

Whether this method is truly the most efficient should depend on how you access the final matrix new. If you access it column-wise, for example, then it should be equivalent as accessing AA as a vector with a stride of 2, in which case the implementation and hardware likely speed it up to as fast as column-wise access of a regular matrix. Your mileage with other access patterns may vary.