'===========================================================================
' Subject: MATRIX INVERSE ALGORITHM           Date: 09-27-99 (08:40)       
'  Author: Robert L. Roach                    Code: QB, QBasic, PDS        
'  Origin: rroach@cvd-pro.com               Packet: ALGOR.ABC
'===========================================================================
REM---------- MATRIX INVERSE ALGORITHM ----------
REM
REM     This program call the MATINV subroutine which finds
REM      the inverse of an A(,) matrix.
REM
REM-------------------------------------------------------------
        DEFDBL A-H, O-Z
        DEFINT I-N

        LL = 3: LLM = 3
        DIM A(LL, LL), AI(LL, LL), AO(LL, LL), B(LL, LL)

REM---------- MATRIX TO BE INVERTED
        A(1, 1) = 2
        A(2, 1) = 2
        A(3, 1) = 4
       
        A(1, 2) = 2
        A(2, 2) = 2
        A(3, 2) = 1
       
        A(1, 3) = 0
        A(2, 3) = 1
        A(3, 3) = 1

REM------- SAVE ORIGINAL MATRIX IN AO(,)
        FOR J = 1 TO LL
          FOR I = 1 TO LL
            AO(I, J) = A(I, J)
          NEXT
        NEXT

REM----------- IDENTITY MATRIX ------------
        FOR L2 = 1 TO LL
          FOR L1 = 1 TO LL
            AI(L1, L2) = 0
          NEXT
          AI(L2, L2) = 1
        NEXT

REM-------- PRINT THE MATRIX ---------
        CLS
        LOCATE 1, 10: PRINT "Original Matrix"
        ROW = 1
       
        LLL = LLM
        IF LLM > LL THEN LLL = LL
       
        FOR J = 1 TO LLL
          ROW = ROW + 1
          SUM = 0
          FOR I = 1 TO LLL
            COL = 2 + 10 * (I - 1)
            LOCATE ROW, COL
            PRINT USING " ##.##### "; AO(I, J)
          NEXT
        NEXT

REM-------- NOW INVERT THE MATRIX -----------
        GOSUB 1000


REM-------- CHECK BY MULTIPLYING THE INVERSE BY THE ORIGINAL
        FOR LA = 1 TO LL
          FOR LB = 1 TO LL
            B(LB, LA) = 0
            FOR L1 = 1 TO LL
              B(LB, LA) = B(LB, LA) + AO(L1, LA) * AI(LB, L1)
            NEXT
          NEXT
        NEXT

REM-------- PRINT THE INVERSE ---------
        ROW = ROW + 2
        LOCATE ROW, 10: PRINT "Inverse Matrix"
        LR1 = (LL - LLM) / 2
        LR1 = 1
        
        FOR J = LR1 TO LR1 + LLL - 1
'        FOR J = 1 TO LL
          ROW = ROW + 1
          SUM = 0
          FOR I = LR1 TO LR1 + LLL - 1
'          FOR I = 1 TO LL
            COL = 2 + 10 * (I - LR1)
            LOCATE ROW, COL
            PRINT USING " ##.######"; AI(I, J)
          NEXT
        NEXT

REM-------- PRINT THE CHECK MATRIX ---------
        ROW = ROW + 2
        LOCATE ROW, 10: PRINT "A*AI"
        FOR J = 1 TO LLL
          ROW = ROW + 1
          FOR I = 1 TO LLL
            COL = 2 + 10 * (I - 1)
            LOCATE ROW, COL
            PRINT USING " ##.##### "; B(I, J)
          NEXT
        NEXT

REM----------- DONE ---------------------
        END


1000 REM----------------- INVERT A MATRIX ----------------------
REM
REM      This subroutine inverts the matrix A.  The inverse
REM      is returned in the matrix AI.  Unfortunately, A itself
REM      is messed up upon completion, which is why I stored
REM      the original A matrix in AO in the main program.
REM
REM----------------------------------------------------------------------
        FOR LC = 1 TO LL

REM-------- CHECK DIAGONAL OF THIS ROW FOR ZERO
REM   Note:  if so, just add one of the other rows to it
          IF ABS(A(LC, LC)) < 1E-10 THEN
'            PRINT "    Aieee...a zero in the diagonal..."
            FOR LCA = LC + 1 TO LL
              IF LCA = LC GOTO 1090
              IF ABS(A(LC, LCA)) > 1E-10 THEN
                FOR LCB = 1 TO LL
                  A(LCB, LC) = A(LCB, LC) + A(LCB, LCA)
                  AI(LCB, LC) = AI(LCB, LC) + AI(LCB, LCA)
                NEXT
                GOTO 1100
              END IF
1090     NEXT
          END IF

1100 REM---- MAKE THE DIAGONAL UNITY BY DIVIDING THE ROW BY IT
          AIN = 1 / A(LC, LC)
          FOR LCA = 1 TO LL
            A(LCA, LC) = AIN * A(LCA, LC)
            AI(LCA, LC) = AIN * AI(LCA, LC)
          NEXT

REM-------- ELIMINATE THE REMAINING ELEMENTS IN THE LCth COLUMN
          FOR LCA = 1 TO LL
            IF LCA = LC GOTO 1150
            AF = A(LC, LCA)
            FOR LCB = 1 TO LL
              A(LCB, LCA) = A(LCB, LCA) - AF * A(LCB, LC)
              AI(LCB, LCA) = AI(LCB, LCA) - AF * AI(LCB, LC)
            NEXT
1150   NEXT

        NEXT

REM------------------------------------------------------------------------
         RETURN
