vanand@molotov.eng.clemson.edu (Anand Lakshmikumaran) (06/05/90)
Hi Folks ! I encountered a very odd error in a couple of my FORTRAN programs. I have debugged the programs to the point that i know where the error occurs but can't understand why that error should occur. I have simplified one of the programs and am attaching it below so that if anyone have faced a similar problem before or know how to avoid this error could kindly reply to me by email. This program is just a part of a bigger program. The problem is: I am trying to invert a matrix 'b' (which in this example is of order 4 but could be much bigger actually) using a subroutine. 'write statement' no. 1 gives the correct value but 'write statement' no. 2 which SHOULD give the same value doesn't. I have attached the output also. The odd part of it is that if i change the dimension of 'b' in my first statement to 'b(4,4)' (i.e. which is the actual array size for this particular example) then the output is accurate. The correct values of 'b inverse' is also attached. P.S. I have tried to run it on both SUN Fortran and VAX Fortran. Both of them give the same error. My email address is vanand@eng.clemson.edu Thanks for reading through this. -ANAND V. L. vanand@eng.clemson.edu dimension b(50,50) n = 4 do i = 1,n,1 b(i,i) = 4.0 if(i.ne.(n))then b(i,i+1) = 1. b(i+1,i) = 1. endif enddo c*** WRITE STATEMENT NO.1 ******************************************* do i = 1,n,1 write(*,*)(b(i,j),j=1,n,1) enddo C************************************************************************** call minv(n,b) C*** WRITE STATEMENT NO. 4 ******************************************* do i = 1,n,1 write(*,*)(b(i,j),j=1,n,1) enddo C************************************************************************** end C ******************************************************** C MINV IS MATRIX INVERSE. C ******************************************************** SUBROUTINE MINV(N,A) dimension a(n,n) C********************************************************************** C modified from p. 197 of James,Smith,& Wolford C matrix inversion using Gauss-Jordan reduction C inverted matrix overlays original matrix in memory C C input: matrix a to be inverted, N=order of matrix [A] C C output: a is replaced by its inverse (original destroyed) C C calculate elements of new matrix C********************************************************************** C*** WRITE STATEMENT NO. 2 **************************************** do 100 i = 1,n,1 write(*,*)(a(i,j),j=1,n,1) 100 continue C************************************************************************ DO 600 K=1,N C calculate new elements of pivot row do 20 J=1,N IF (J.ne.K) THEN A(K,J)=A(K,J)/A(K,K) endif 20 continue C calculate element replacing pivot element A(K,K)=1.d0/A(K,K) C calculate new elements not in pivot row or pivot column do 40 I=1,N do 30 J=1,N if ((I.ne.K).and.(J.ne.K)) then A(i,j)=A(i,j)-A(k,j)*A(i,k) endif 30 continue 40 CONTINUE C calculate replacement elements for pivot column C (except pivot element) do 50 i=1,N if(i.ne.K) a(i,K)=-a(i,K)*a(K,K) 50 CONTINUE 600 continue C*** WRITE STATEMENT NO. 3 ******************************************** do 200 i = 1,n,1 write(*,*)(a(i,j),j=1,n,1) 200 continue C**************************************************************************** return end THE OUTPUT ON SUN FORTRAN WAS AS FOLLOWS WRITE STATEMENT NO. 1 4.00000 1.00000 0. 0. 1.00000 4.00000 1.00000 0. 0. 1.00000 4.00000 1.00000 0. 0. 1.00000 4.00000 WRITE STATEMENT NO. 2 4.00000 0. 0. 0. 1.00000 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. WRITE STATEMENT NO. 3 -\NA\N \NA\N -\NA\N -\NA\N \NA\N \NA\N \NA\N \NA\N -\NA\N -\NA\N -\NA\N -\NA\N -\NA\N -\NA\N -\NA\N -\NA\N WRITE STATEMENT NO. 4 -\NA\N 1.00000 0. 0. \NA\N 4.00000 1.00000 0. -\NA\N 1.00000 4.00000 1.00000 -\NA\N 0. 1.00000 4.00000 THE CORRECT VALUES OF THE MATRIX B AND ITS INVERSE ARE MATRIX B 4.0 1.0 0.0 0.0 1.0 4.0 1.0 0.0 0.0 1.0 4.0 1.0 0.0 0.0 1.0 4.0 B INVERSE 0.267943 -7.17703E-02 1.91388E-02 -4.78469E-03 -7.17703E-02 0.287081 -7.65550E-02 1.91388E-02 1.91388E-02 -7.65550E-02 0.287081 -7.17703E-02 -4.78469E-03 1.91388E-02 -7.17703E-02 0.267943
sun@me.utoronto.ca (Andy Sun Anu-guest) (06/05/90)
In article <9206@hubcap.clemson.edu> vanand@molotov.eng.clemson.edu (Anand Lakshmikumaran) writes: >Hi Folks ! > I encountered a very odd error in a couple of my FORTRAN programs. >I have debugged the programs to the point that i know where the error occurs >but can't understand why that error should occur. I have simplified one of >the programs and am attaching it below so that if anyone have faced a similar >problem before or know how to avoid this error could kindly reply to me by email. >This program is just a part of a bigger program. > The problem is: > I am trying to invert a matrix 'b' (which in this example is of order 4 >but could be much bigger actually) using a subroutine. 'write statement' no. 1 >gives the correct value but 'write statement' no. 2 which SHOULD give the same value >doesn't. I have attached the output also. > The odd part of it is that if i change the dimension of 'b' in my first statement >to 'b(4,4)' (i.e. which is the actual array size for this particular example) then >the output is accurate. The correct values of 'b inverse' is also attached. > >P.S. I have tried to run it on both SUN Fortran and VAX Fortran. Both of them > give the same error. > >My email address is vanand@eng.clemson.edu > >Thanks for reading through this. >-ANAND V. L. >vanand@eng.clemson.edu > > > dimension b(50,50) > n = 4 > do i = 1,n,1 > b(i,i) = 4.0 > if(i.ne.(n))then > b(i,i+1) = 1. > b(i+1,i) = 1. > endif > enddo > >c*** WRITE STATEMENT NO.1 ******************************************* > > do i = 1,n,1 > write(*,*)(b(i,j),j=1,n,1) > enddo > >C************************************************************************** > > call minv(n,b) > >C*** WRITE STATEMENT NO. 4 ******************************************* > > do i = 1,n,1 > write(*,*)(b(i,j),j=1,n,1) > enddo > >C************************************************************************** > > end > The rest of the stuff deleted... A lot of th first year students I tutored made this mistake. Nothing wrong with the subroutine, what's wrong is the way you pass the parameters. You are partly correct in saying that changing the dimension to (4,4) works. In fact, if you declared an (m,n) array in the main program, no matter how small a portion that you are passing to a subroutine (e.g. you've declared dimension (100,100) but just use (2,2)), you HAVE TO pass the maximum ROW element over. In my example, you have to pass (100,2) as parameters, not (2,2) or else you array got all messed up. In your case, you b is ALWAYS 50 if (50,50) is what you've declared. Fortran stores your 2D array (say, a 3x3) sequentially like this: 1 (1,1) 2 (1,2) 3 (1,3) (1,1) (1,2) (1,3) 4 (2,1) (2,1) (2,2) (2,3) 5 (2,2) (3,1) (3,2) (3,3) 6 (2,3) 7 (3,1) 8 (3,2) 9 (3,3) if you only pass a 2x2 over to a subroutine, this is what you are actually passing: 1 (1,1) 2 (1,2) (1,1) (1,2) 3 (1,3) (1,3) (2,1) 4 (2,1) You see why it get all messed up. If you are a good programmer and initialized the array to zeros first once you delcared it, you will find zeros all over the place if you pass the array the way you did. If you don't initialize it, you can get ANYTHING: random numbers depending on what those memory locations got in them. Andy _______________________________________________________________________________ Andy Sun | Internet: sun@me.utoronto.ca University of Toronto, Canada | UUCP : ...!utai!me!sun Dept. of Mechanical Engineering | BITNET : sun@me.utoronto.BITNET