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)?
MATLAB: Turn every element of complex matrix into another matrix
69 Views Asked by Cathematics AtThere are 3 best solutions below
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.
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.
Here's a way using
kron. It is probably a little wasteful in terms of operations:This example gives
The following approach is clunkier, but perhaps more efficient:
Like before, this gives