Odd behaviour of 2x2-matrix and 2x1-vector operation

8 views (last 30 days)
Consider a 2x2 matrix A with columns uncorrelated, and a vector x:
A = [ a b ]
[-b' a']
x = [ a']
[ b']
where a and b are complex scalar. The product of A*x is supposed to be mathematically:
A*x = [ a*a'+b*b' ] = [ a*a'+b*b' ]
[-b'*a'+a'*b'] [ 0 ]
In matlab 2012b, I tried to compare A*x matrix operation and the element-wise operations such as a*a'+b*b' and -b'*a'+a'*b'. Both results happen to be different with some random pairs of a and b. a*a'*b*b' always shows positive real, but matrix operation shows some residual on the imaginary part sometime. Even -b'*a'+a'*b' entry of matrix operation shows such erroneous imaginary part, which is supposed to be zero!
The following script finds the mismatch result and shows the hex forms of the results.
y0, y1, y2, z show the result of different operations:
  • y0 = A*x; % matlab matrix multiply script
  • y1 = mtimes(A,x); % mtimes operation
  • y2 = mvmult_lapack (A, x); % private code using lapack routine (ZGEMV)
  • z = [a*a'+b*b';-b'*a'+a'*b']; % element-wise operation
Result : y2 and z are always same and real, but y0 and y1 have erroneous imaginary part. Note that the real parts of y0 and y1 are different from the real parts of y2 and z by eps, say a difference of the last bit of floating-point format.
Discuss and Question : It is not clear why the A*x script shows the difference from the element-wise operation. It could not be a problem with LAPACK/BLAS. There seems parser or storage register problem in machine code when the matrix operation is called. Is this only preblem with 2012b or my machine?
Test script :
randn('seed',0)
ii=0;
while 1,
ii = ii + 1;
a = randn+i*randn;
b = randn+i*randn;
%
A = [a b; -b' a'];
x = [a'; b'];
y0 = A*x;
y1 = mtimes(A,x);
y2 = mvmult_lapack (A, x);
z = [a*a'+b*b';-b'*a'+a'*b'];
if sum(y0~=z) % break when the results are different!
break
end
if ii==10000
break
end
end
ii
%
a
b
y0
y1
y2
z
y0==z
[num2hex(real(y0)), repmat(' ',[2 1]), num2hex(imag(y0))]
[num2hex(real(y1)), repmat(' ',[2 1]), num2hex(imag(y1))]
[num2hex(real(y2)), repmat(' ',[2 1]), num2hex(imag(y2))]
[num2hex(real(z)), repmat(' ',[2 1]), num2hex(imag(z))]
Output :
ii =
1
a =
1.16495351050066 + 0.626839082632431i
b =
0.0750801546776829 + 0.351606902768522i
y0 =
1.87930836084417 - 3.46944695195361e-18i
0 - 2.08166817117217e-17i
y1 =
1.87930836084417 - 3.46944695195361e-18i
0 - 2.08166817117217e-17i
y2 =
1.87930836084417
0
z =
1.87930836084417
0
ans =
0
0
ans =
3ffe11a5a4cecd1e bc50000000000000
0000000000000000 bc78000000000000
ans =
3ffe11a5a4cecd1e bc50000000000000
0000000000000000 bc78000000000000
ans =
3ffe11a5a4cecd1d 0000000000000000
0000000000000000 0000000000000000
ans =
3ffe11a5a4cecd1d 0000000000000000
0000000000000000 0000000000000000
  1 Comment
Stephen23
Stephen23 on 19 Dec 2014
Maybe you should start a Newsgroup thread about this... it seems like an interesting issue to discuss.

Sign in to comment.

Accepted Answer

Roger Stafford
Roger Stafford on 20 Dec 2014
Both the differences in real parts and the spurious imaginary parts in y0 and y1 are extremely small and are undoubtedly due to rounding differences in the four different methods of computation. Your results show that the real parts differ only in the least significant bits and the imaginary parts are likewise extremely small.
You should realize that simply rearranging the ordering of computations can result in slightly differing results. An example I like to give is:
format hex
(3/14+3/14)+15/14 --> 3ff8000000000000
3/14+(3/14+15/14) --> 3ff7ffffffffffff
Although both should have 1.5 as a result, the second one comes out one bit different from that. That is because there are two operations performed with a rounding after each one, and this is done in a different order in the two cases with a resulting difference in the final result.
The same applies to the operations performed in your four methods. The sequencing of operations is different in the four methods and the results therefore don't exactly match. This is something that has to be accepted in performing numerical computations using digital computers with a finite number of bits accuracy.
  3 Comments
Roger Stafford
Roger Stafford on 20 Dec 2014
The ordering (grouping) for the imaginary part
( (br*ai) + (bi*ar) ) + ( (-ar*bi) + (-ai*br) )
should always produce an exact zero in matlab. That is because two-operand addition and multiplication are always commutative in the IEEE 754 standard. However the ordering
( ( (br*ai) + (bi*ar) ) + (-ar*bi) ) + (-ai*br)
or other similar orderings could easily yield a nonzero, (though of course an extremely small one,) because the associative law does not always hold. Something like the latter method is therefore probably what 'mtimes' is using.
Sung-Eun Jo
Sung-Eun Jo on 22 Dec 2014
I agree. In matlab, 'mtimes' and * operator for complex data should be careful. Their computation ordering may cause numerical errors even in trivial cases such as perfect zero or real value expected.

Sign in to comment.

More Answers (0)

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!