Back in the old days - Conte and deBoore was a nice textbook on Numerical Analysis. I remember using this textbook in my Mechanical Engineering course on Numerical Analysis - of course one could only use Fortran then.
Skip forward to 1987 and I needed a quick inverter to solve a minor problem, so I used the old Conte and de Boore method.
I still have the code and the examples.
The structural analysis package I lifted from 1973 is giving me one or two minor and interesting answers that I wanted to check - nothing major just annoyances as I work out the program. Combined with FEAST it is a treat to use compared to a commerical package, one can get at all the numbers quickly and can play with them.
So I thought I would run out the old program, found the floppy drive, load it into VS 2013 - compiles first time - run out a 30 by 30 test case from the 73 code and get the C and deB to invert the matrix, to see if the results are the same.
Answer was a big NO.
Load up the C and deBoore test case, one can still find a PDF of the textbook online -- must be illegal - but what the heck. Still getting the wrong answer on reading in the data. After a bit of exploration with Watch on VS 2013, I learnt something I had completely forgotten, one can pass a vector through a subroutine call and then declare it as an array in the subroutine. Here was the sticking point - it is in column and not row order. Fixing the input routines solved a simple problem and now I can check the 73 code. Of course one should load up the MKL inverter, but what the heck life is short play hard. I need to put the MKL inverter into the 73 code, that is next.
One of the problems with eigenvectors is visuallying the result. I have DISLIN - but I was darned if I could get it to run at the weekend - just ornery I guess and a 9 year old yellling in my ear, I had a simple bitmap drawer from Japan, so I thought - what the heck it is only simple line sketches. I thought I need to draw lines, circles and some text. I was fun -- text looks like MS DOS prompts after heated to 1200 C, but who cares. It is possible to create bitmaps from a standard FORTRAN program -- of course it is not pretty - but then again neither am I.
Here is the code - very old Fortran - but it still works. and is often said - if it is not broken do not fix it
C ********************************************************************* PROGRAM MATRIX C ********************************************************************* C This is a matrix inversion progamme taken from Conte and deBoor C Elementary Numerical Analysis. C It has been amended to run on an IBM PC under Microsoft Fortran C by John Nichols. C ********************************************************************* implicit character*60(z) DIMENSION Aorg(10000) Dimension A(10000),ainv(10000),b(100),ipivot(100),c(100),d(100) write(*,1) 1 format(1x,'This is an IBM MICROSOFT FORTRAN programme',/ 11x,'from CONTE and de BOOR,amended by John Nichols',/ 21x,'in July 1987.',/ 31x,' Ver. 1.0 --Ph (049 25464).'//) C C ********************************************************************* C C Read input and output devices for files. C C ********************************************************************* C write(*,20) 20 format(1x,'File name for input data : '\) read(*,30)zFILE1 30 format(a12) write(*,40) 40 format(1x,'File name for output data : '\) read(*,50)zFILE2 50 format(a12) C C ********************************************************************* C C Open files for input ouput C C ********************************************************************* C write(*,60) 60 format(1x,'Opening the input file to access data!'/) open(1,file=zFILE1,status='OLD') write(*,70) 70 format(1x,'Opening the output file for data!'/) open(2,file=zFILE2,status='UNKNOWN') C C ********************************************************************* C C Read input data from file 1 C C ********************************************************************* C 100 continue c(1:100)=0.0 read(1,80)N 80 format(I3) write(*,90)N 90 format(1x,'The matrix size is ',i2/) read(1,*)(d(j),j=1,n) read(1,*)N1 nsq=N*N read(1,*)(a(j),j=1,nsq) do 102 i = 1,nsq aorg(i) = a(i) 102 end do write(*,101)(a(j),j=1,nsq) 101 format(3(2x,F10.6)) write(*,101)(d(j),j=1,n) C C ********************************************************************* C C Call factor subroutine C C ********************************************************************* C write(*,150) 150 format(1x,'At the factor subroutine!',/) call factor(a,a,ipivot,b,n,iflag) go to (120,110),iflag 110 continue C C ********************************************************************* C C The matrix is singular C C ********************************************************************* C write(*,130) 130 format(1x,'This matrix is singular have another shot!',/) go to 210 120 continue C C ********************************************************************* C C Call subst subroutine C C ********************************************************************* C do 140 I=1,N b(i)=0.0 140 continue ibeg=1 do 160 j=1,N b(j)=1.0 call subst(a,b,ainv(ibeg),ipivot,n) b(j)=0.0 ibeg=ibeg+N 160 continue C C ********************************************************************* C C Inverted matrix results C C ********************************************************************* C write(2,170) write(*,170) 170 format(1x,'The computed inverse is ',//) write(2,101)(ainv(j),j=1,nsq) write(*,101)(ainv(j),j=1,nsq) 180 format((3F10.5)) 210 continue call MatrixResult(aorg, ainv,d,c,n) C C ********************************************************************* C C End of programme C C ********************************************************************* C write(*,200) 200 format(1x,'The end of the programme',/) end C C ********************************************************************* C Subroutine MatrixResult(a,ainv,d,c, n) C C ********************************************************************* C dimension a(n,n),d(n),c(n),ainv(n,n), f(n,n) integer n,i,j do 100 i = 1,n do 200 j =1,n c(i) = a(i,j)*d(i)+c(i) 200 Continue 100 Continue f(1:n,1:n)=0.0 do 400 i=1, n do 300 j=1, n do 250 k=1, n f(i,j)=f(i,j)+a(j,k)*ainv(k,i) 250 enddo 300 end do 400 end do do 500 i = 1,n write(*,180)(F(i,j),j=1,n) 500 end do 180 format((30F4.1)) write(*,70) 70 format(1x,'Opening the C data!'/) write(*,*)(c(i),i=1,n) return end C C C ********************************************************************* C Subroutine Factor(a,w,ipivot,d,n,iflag) C C ********************************************************************* C dimension a(n,n),w(n,n),ipivot(n),d(n) C C ********************************************************************* C C initialize vectors C C ********************************************************************* C iflag=1 do 10 i=1,n ipivot(i)=i rowmax=0.0 do 20 j=1,n w(i,j)=a(i,j) rowmax=amax1(rowmax,abs(w(i,j))) 20 continue if(rowmax .eq. 0.0) go to 999 d(i)=rowmax 10 continue C C ********************************************************************* C C Gaussian elimination with scaled partial pivotting C C ********************************************************************* C nm1=n-1 if(nm1 .eq. 0) return do 30 k=1,nm1 j=k kp1=k+1 ip=ipivot(k) colmax=abs(w(ip,k))/d(ip) do 40 i=kp1,n ip=ipivot(i) awikov=abs(w(ip,k))/d(ip) if (awikov .le. colmax ) go to 40 colmax=awikov j=i 40 continue if (colmax .eq. 0.0) go to 999 ipk=ipivot(j) ipivot(j)=ipivot(k) ipivot(k)=ipk do 30 i=kp1,n ip=ipivot(i) w(ip,k)=w(ip,k)/w(ipk,k) ratio=-w(ip,k) do 30 j=kp1,n w(ip,j)=ratio*w(ipk,j)+w(ip,j) 30 continue if (w(ip,n) .eq. 0.0) go to 999 return 999 iflag=2 return end C C ********************************************************************* C subroutine subst (w,b,x,ipivot,n) C C ********************************************************************* C dimension w(n,n),b(n),x(n),ipivot(n) if (n .gt. 1) go to 10 x(1)=b(1)/w(1,1) return 10 continue ip=ipivot(1) x(1)=b(ip) do 15 k=2,n ip=ipivot(k) km1=k-1 sum=0.0 do 14 j=1,km1 sum=w(ip,j)*x(j)+sum 14 continue x(k)=b(ip)-sum 15 continue x(n)=x(n)/w(ip,n) k=n do 20 np1mk=2,n kp1=k k=k-1 ip=ipivot(k) sum=0.0 do 19 j=kp1,n sum=w(ip,j)*x(j)+sum 19 continue x(k)=(x(k)-sum)/w(ip,k) 20 continue return end