Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28445 Discussions

How could I compare two dense matrices with the same dimensions?

SergeyKostrov
Valued Contributor II
333 Views
I'm currently porting some Fortran codes to C/C++ and my question is: How could I compare two dense matrices with the same dimensions? For exampe, ... ALLOCATE ( A( n,m ) ) ALLOCATE ( B( n,m ) ) ... A = 0 B = 0 ... ! Some processing... ... Could I use: ... IF A == B THEN WRITE(*,"(A)"),'Matrix A equal to Matrix B' ELSEIF THEN WRITE(*,"(A)"),'Matrix A not equal to Matrix B' ENDIF ... Thanks in advance.
0 Kudos
10 Replies
IanH
Honored Contributor II
333 Views

[fortran]IF (ALL(A == B)) THEN

...

ELSE

...

END IF[/fortran]

0 Kudos
SergeyKostrov
Valued Contributor II
333 Views
>>IF (ALL(A == B)) THEN >>... >>ELSE >>... >>END IF Thank you, Ian! PS: It is so simple :)
0 Kudos
DavidWhite
Valued Contributor II
333 Views

Remember that if the variables are real or double precision, then your equals test is likely to fail if the only differences are due to rounding errors.

If this is what you want, then OK, but you may want to look at the magnitudes of the differences.

Regards,

David

0 Kudos
John_Campbell
New Contributor II
333 Views

If you want to be careful and assuming matrices A and B are real, you could try something like:

Logical function same_matrix (a,b,n,m)
real*8 a(n,m), b(n,m)
!
integer*4 i,j
real*8 err_max, max_val, tolerance
!
max_val = 0
err_max = 0
do j = 1,m
  do i = 1,n
   max_val = max (max_val, abs(a(i,j)) )
   err_max = max (err_max, abs(a(i,j)-b(i,j)) )
  end do
end do
!
tolerance = epsilon (max_val) * max_val * fudge_factor
same_matrix =  (err_max < tolerance)
end function same_matrix 

tolerance might still need some more work.
If a,b are integer or logical, then tolerance is much simpler, but I would still use DO, rather than array syntax.
Never addressed complex !!

John

0 Kudos
SergeyKostrov
Valued Contributor II
333 Views
>>If you want to be careful and assuming matrices A and B are real... Yes, they are real and in Fortran codes two different matrix multiplication methods are used. Since sizes of matricies could be up to 96Kx96K or so, ( limit due to amount of memory on my computer ) a verification that takes into account epsilon is a very good solution. Thank you.
0 Kudos
jimdempseyatthecove
Honored Contributor III
333 Views

John,

The err_max=... needs to be adjusted such that the difference in the values is relative to the magnitude of the values.

 Jim Dempsey

0 Kudos
JVanB
Valued Contributor II
333 Views

jimdempseyatthecove wrote:

The err_max=... needs to be adjusted such that the difference in the values is relative to the magnitude of the values.

The Fortran SPACING intrinsic is great for this. An example:

[fortran]   integer ulps

   ulps = 4

   if(all(abs(a-b)<ulps*spacing(max(abs(a),abs(b))))) then[/fortran]

0 Kudos
TimP
Honored Contributor III
333 Views

if(all(abs(a-b)<ulps*spacing(max(abs(a),abs(b))))) then

may leave something to be desired in terms of minimizing memory traffic and parallelizing a problem as large as mentioned above.

0 Kudos
JVanB
Valued Contributor II
333 Views

TimP (Intel) wrote:

if(all(abs(a-b)<ulps*spacing(max(abs(a),abs(b))))) then

may leave something to be desired in terms of minimizing memory traffic and parallelizing a problem as large as mentioned above.

If memory traffic is an issue then the above statement has the same amount of memory traffic as the less careful

if(all(a==b)) then

and so should then execute in essentially the same time because all of the functions and operators in the more complicated argument to ALL are elemental.

0 Kudos
SergeyKostrov
Valued Contributor II
333 Views
Thanks to everybody for all your comments, ideas and codes! I got it and will stick to first two suggestions from Ian and John.
0 Kudos
Reply