Hi,
I have tried your code (in the first post), and I think you need to declare the work variables
as double precision (in consistent with input/output arrays). Specifically, this line
REAL :: summ,xmult,xmult2,xmult3
should be modified as
REAL*8 :: summ,xmult,xmult2,xmult3
or
double precision :: summ,xmult,xmult2,xmult3
etc (there are also other portable ways to write this, but the point is to use double precision consistently).
-----------
Test:
If I change your routine so that it receives ncols and nrows as arguments
SUBROUTINE MATINV(MATSUM,INVERSE, ncols, nrows )
IMPLICIT NONE
Double Precision, INTENT(IN),DIMENSION(100,100) :: MATSUM
Double Precision, INTENT(OUT),DIMENSION(100,100) :: INVERSE
INTEGER :: I,J,NROWS,NCOLS,M,N,K,p,q
REAL*8 :: summ,xmult,xmult2,xmult3
Double Precision, DIMENSION(100,100) :: A, Ainv, Ident
!-- NROWS=7
!-- NCOLS=7
...
and write the main program as follows,
program main
implicit none
integer, parameter :: n = 7
real*8 A( 100, 100 ), Ainv( 100, 100 ), t( n, n ) !! t = tmp array
integer i, j, itest
!>>>
itest = 2
!<<<
selectcase ( itest )
case ( 1 ) !! simple regular matrix
do i = 1, n
do j = 1, n
t( i, j ) = 1.0d0 / ( abs(i-j) + 1.0d0 )
enddo
enddo
case ( 2 ) !! OP's matrix in double precision
t(1,:) = [ 744.5047d0, 909.5175d0, 983.0251d0, 1024.6988d0, &
1051.5530d0, 1070.3036d0, 1084.1393d0 ]
t(2,:) = [ 909.5175d0, 1112.7881d0, 1203.5504d0, 1255.0658d0, &
1288.2851d0, 1311.4910d0, 1328.6199d0 ]
t(3,:) = [ 983.0251d0, 1203.5504d0, 1302.1218d0, 1358.0994d0, &
1394.2078d0, 1419.4376d0, 1438.0635d0 ]
t(4,:) = [ 1024.6988d0, 1255.0658d0, 1358.0994d0, 1416.6292d0, &
1454.3913d0, 1480.7802d0, 1500.2639d0 ]
t(5,:) = [ 1051.5530d0, 1288.2851d0, 1394.2078d0, 1454.3913d0, &
1493.2255d0, 1520.3664d0, 1540.4069d0 ]
t(6,:) = [ 1070.3036d0, 1311.4910d0, 1419.4376d0, 1480.7802d0, &
1520.3664d0, 1548.0349d0, 1568.4664d0 ]
t(7,:) = [ 1084.1393d0, 1328.6199d0, 1438.0635d0, 1500.2639d0, &
1540.4069d0, 1568.4664d0, 1589.1877d0 ]
case ( 3 ) !! OP's matrix in single precision
t(1,:) = [ 744.5047, 909.5175, 983.0251, 1024.6988, &
1051.5530, 1070.3036, 1084.1393 ]
t(2,:) = [ 909.5175, 1112.7881, 1203.5504, 1255.0658, &
1288.2851, 1311.4910, 1328.6199 ]
t(3,:) = [ 983.0251, 1203.5504, 1302.1218, 1358.0994, &
1394.2078, 1419.4376, 1438.0635 ]
t(4,:) = [ 1024.6988, 1255.0658, 1358.0994, 1416.6292, &
1454.3913, 1480.7802, 1500.2639 ]
t(5,:) = [ 1051.5530, 1288.2851, 1394.2078, 1454.3913, &
1493.2255, 1520.3664, 1540.4069 ]
t(6,:) = [ 1070.3036, 1311.4910, 1419.4376, 1480.7802, &
1520.3664, 1548.0349, 1568.4664 ]
t(7,:) = [ 1084.1393, 1328.6199, 1438.0635, 1500.2639, &
1540.4069, 1568.4664, 1589.1877 ]
endselect
A( 1:n, 1:n ) = t(:,:)
call matinv( A, Ainv, n, n )
print *, "Ainv = "
do i = 1, n
print "(*(f12.4))", Ainv( i, 1:n )
enddo
t = matmul( A( 1:n, 1:n ), Ainv( 1:n, 1:n ) )
print *, "A * Ainv = "
do i = 1, n
print "(*(f12.4))", t( i, 1:n )
enddo
end program
we can get the following results:
-----
For itest = 1 :
---------------------------------------------------
>>>>>>>>Input Matrix<<<<<<<<
1.0000 0.5000 0.3333 0.2500 0.2000 0.1667 0.1429
0.5000 1.0000 0.5000 0.3333 0.2500 0.2000 0.1667
0.3333 0.5000 1.0000 0.5000 0.3333 0.2500 0.2000
0.2500 0.3333 0.5000 1.0000 0.5000 0.3333 0.2500
0.2000 0.2500 0.3333 0.5000 1.0000 0.5000 0.3333
0.1667 0.2000 0.2500 0.3333 0.5000 1.0000 0.5000
0.1429 0.1667 0.2000 0.2500 0.3333 0.5000 1.0000
---------------------------------------------------
Ainv =
1.3601 -0.5884 -0.1056 -0.0546 -0.0364 -0.0287 -0.0350
-0.5884 1.6137 -0.5435 -0.0829 -0.0402 -0.0267 -0.0287
-0.1056 -0.5435 1.6213 -0.5400 -0.0812 -0.0402 -0.0364
-0.0546 -0.0829 -0.5400 1.6225 -0.5400 -0.0829 -0.0546
-0.0364 -0.0402 -0.0812 -0.5400 1.6213 -0.5435 -0.1056
-0.0287 -0.0267 -0.0402 -0.0829 -0.5435 1.6137 -0.5884
-0.0350 -0.0287 -0.0364 -0.0546 -0.1056 -0.5884 1.3601
A * Ainv =
1.0000 0.0000 -0.0000 0.0000 -0.0000 0.0000 0.0000
0.0000 1.0000 -0.0000 0.0000 -0.0000 -0.0000 0.0000
0.0000 0.0000 1.0000 0.0000 -0.0000 0.0000 -0.0000
0.0000 -0.0000 -0.0000 1.0000 0.0000 0.0000 -0.0000
-0.0000 0.0000 -0.0000 -0.0000 1.0000 -0.0000 0.0000
-0.0000 0.0000 -0.0000 -0.0000 -0.0000 1.0000 0.0000
-0.0000 -0.0000 -0.0000 -0.0000 -0.0000 0.0000 1.0000
----
For itest = 2:
---------------------------------------------------
>>>>>>>>Input Matrix<<<<<<<<
744.5047 909.5175 983.0251 1024.6988 1051.5530 1070.3036 1084.1393
909.5175 1112.7881 1203.5504 1255.0658 1288.2851 1311.4910 1328.6199
983.0251 1203.5504 1302.1218 1358.0994 1394.2078 1419.4376 1438.0635
1024.6988 1255.0658 1358.0994 1416.6292 1454.3913 1480.7802 1500.2639
1051.5530 1288.2851 1394.2078 1454.3913 1493.2255 1520.3664 1540.4069
1070.3036 1311.4910 1419.4376 1480.7802 1520.3664 1548.0349 1568.4664
1084.1393 1328.6199 1438.0635 1500.2639 1540.4069 1568.4664 1589.1877
---------------------------------------------------
Ainv =
-76.5341 1348.1077 -2930.3976 471.9861 1596.9489 914.7758 -1319.4799
1348.1077 -9685.4287 16217.1709 -444.2072 -8633.6875 -6213.9708 7423.6791
-2930.3976 16217.1709 -25394.9467 5472.2177 8223.5511 4896.2298 -6548.5709
471.9861 -444.2073 5472.2177 -20792.6764 14657.9507 11719.0732 -11047.5255
1596.9489 -8633.6874 8223.5510 14657.9506 -21308.0561 -810.0949 6302.8895
914.7758 -6213.9709 4896.2299 11719.0733 -810.0951 -28224.5399 17718.8556
-1319.4799 7423.6791 -6548.5710 -11047.5256 6302.8896 17718.8556 -12548.3770
A * Ainv =
1.0000 0.0000 0.0000 -0.0000 0.0000 0.0000 -0.0000
0.0000 1.0000 -0.0000 -0.0000 0.0000 0.0000 -0.0000
0.0000 0.0000 1.0000 -0.0000 0.0000 0.0000 -0.0000
0.0000 0.0000 0.0000 1.0000 0.0000 0.0000 -0.0000
0.0000 0.0000 0.0000 -0.0000 1.0000 -0.0000 -0.0000
-0.0000 0.0000 0.0000 -0.0000 0.0000 1.0000 -0.0000
-0.0000 0.0000 0.0000 -0.0000 0.0000 0.0000 1.0000
-----
For itest = 3:
---------------------------------------------------
>>>>>>>>Input Matrix<<<<<<<<
744.5047 909.5175 983.0251 1024.6989 1051.5530 1070.3036 1084.1393
909.5175 1112.7881 1203.5504 1255.0658 1288.2852 1311.4910 1328.6199
983.0251 1203.5504 1302.1218 1358.0994 1394.2078 1419.4376 1438.0635
1024.6989 1255.0658 1358.0994 1416.6292 1454.3914 1480.7802 1500.2639
1051.5530 1288.2852 1394.2078 1454.3914 1493.2255 1520.3665 1540.4069
1070.3036 1311.4910 1419.4376 1480.7802 1520.3665 1548.0349 1568.4664
1084.1393 1328.6199 1438.0635 1500.2639 1540.4069 1568.4664 1589.1877
---------------------------------------------------
Ainv =
1226.2858 -5381.5101 5434.5522 3357.7945 -4613.9139 -2745.1360 2756.5439
-5381.5101 25499.1781 -27231.1496 -17280.8722 24226.6250 15920.4866 -15887.3775
5434.5522 -27231.1496 32083.1816 14710.2002 -27275.0827 -13230.9528 15635.8056
3357.7945 -17280.8722 14710.2001 24727.0036 -18651.0769 -29212.4668 22412.1919
-4613.9139 24226.6250 -27275.0827 -18651.0769 23751.1226 23633.8067 -21165.6786
-2745.1360 15920.4865 -13230.9528 -29212.4668 23633.8067 30434.5518 -24832.8470
2756.5439 -15887.3775 15635.8056 22412.1919 -21165.6785 -24832.8470 21119.9518
A * Ainv =
1.0000 0.0000 0.0000 0.0000 -0.0000 -0.0000 0.0000
0.0000 1.0000 0.0000 0.0000 -0.0000 -0.0000 0.0000
0.0000 -0.0000 1.0000 0.0000 -0.0000 -0.0000 0.0000
0.0000 -0.0000 0.0000 1.0000 -0.0000 -0.0000 0.0000
0.0000 -0.0000 0.0000 0.0000 1.0000 -0.0000 0.0000
0.0000 -0.0000 0.0000 0.0000 -0.0000 1.0000 0.0000
0.0000 -0.0000 0.0000 0.0000 -0.0000 -0.0000 1.0000
-----
Please note that the input matrix elements also need to be given in double precision.
Indeed, in the above example, "Ainv" changes drastically if you enter the input matrix in
single precision.
-----
To see the reason, I also tried the same calculation using Julia.
# test.jl (note: slow because of the use of global variables)
put = println
A = [
744.5047 909.5175 983.0251 1024.6988 1051.5530 1070.3036 1084.1393 ;
909.5175 1112.7881 1203.5504 1255.0658 1288.2851 1311.4910 1328.6199 ;
983.0251 1203.5504 1302.1218 1358.0994 1394.2078 1419.4376 1438.0635 ;
1024.6988 1255.0658 1358.0994 1416.6292 1454.3913 1480.7802 1500.2639 ;
1051.5530 1288.2851 1394.2078 1454.3913 1493.2255 1520.3664 1540.4069 ;
1070.3036 1311.4910 1419.4376 1480.7802 1520.3664 1548.0349 1568.4664 ;
1084.1393 1328.6199 1438.0635 1500.2639 1540.4069 1568.4664 1589.1877 ]
# A = [ 1.0 / (abs(i-j)+1.0) for i=1:7, j=1:7 ] # for itest = 1
put( "A = " )
display( A )
put()
put( "inv(A) = " )
Ainv = inv( A )
display( Ainv )
put()
@show maxabs( A * Ainv - eye( size(A,1) ) )
put( "A * Ainv =" )
display( A * Ainv )
put()
D, V = eig( A )
put( "eigvals = " )
display( D )
put()
@show cond( A )
@show rank( A )
-----
Run:
$ julia test.jl
We get
A =
7x7 Array{Float64,2}:
744.505 909.518 983.025 1024.7 1051.55 1070.3 1084.14
909.518 1112.79 1203.55 1255.07 1288.29 1311.49 1328.62
983.025 1203.55 1302.12 1358.1 1394.21 1419.44 1438.06
1024.7 1255.07 1358.1 1416.63 1454.39 1480.78 1500.26
1051.55 1288.29 1394.21 1454.39 1493.23 1520.37 1540.41
1070.3 1311.49 1419.44 1480.78 1520.37 1548.03 1568.47
1084.14 1328.62 1438.06 1500.26 1540.41 1568.47 1589.19
inv(A) =
7x7 Array{Float64,2}:
-76.5341 1348.11 -2930.4 471.986 1596.95 914.776 -1319.48
1348.11 -9685.43 16217.2 -444.207 -8633.69 -6213.97 7423.68
-2930.4 16217.2 -25394.9 5472.22 8223.55 4896.23 -6548.57
471.986 -444.207 5472.22 -20792.7 14658.0 11719.1 -11047.5
1596.95 -8633.69 8223.55 14658.0 -21308.1 -810.095 6302.89
914.776 -6213.97 4896.23 11719.1 -810.095 -28224.5 17718.9
-1319.48 7423.68 -6548.57 -11047.5 6302.89 17718.9 -12548.4
maxabs(A * Ainv - eye(size(A,1))) = 1.4901161193847656e-8
A * Ainv =
7x7 Array{Float64,2}:
1.0 2.79397e-9 -5.58794e-9 … 7.45058e-9 0.0 -1.86265e-9
0.0 1.0 -1.86265e-9 1.02445e-8 -3.72529e-9 -1.86265e-9
-1.16415e-9 9.31323e-9 1.0 1.30385e-8 3.72529e-9 -7.45058e-9
-4.65661e-10 0.0 0.0 1.30385e-8 3.72529e-9 3.72529e-9
-2.32831e-10 3.72529e-9 -1.86265e-9 1.0 0.0 0.0
-4.65661e-10 9.31323e-9 -5.58794e-9 … 1.49012e-8 1.0 -7.45058e-9
-6.98492e-10 5.58794e-9 -1.30385e-8 1.11759e-8 0.0 1.0
eigvals =
7-element Array{Float64,1}:
-3.86428e-5
-2.78764e-5
-1.69139e-5
0.000363563
0.0108282
4.69211
9201.79
cond(A) = 5.440367717196925e8
rank(A) = 7
So we see that:
(1) Ainv agrees with the result of your code for itest=2, but not for
itest = 3; and,
(2) the condition number cond(A) is very large (on the order of 10^8),
so any contamination by single-precision literals or variables may change the result...
Best,
S