Vous êtes sur la page 1sur 6

DECLARE FUNCTION CABS# (X#, Y#)

DECLARE SUB CDIV (Z1#(), Z2#(), Z#())


DECLARE SUB CMUL (Z1#(), Z2#(), Z#())
'**********************************************************************
'*
Solving a complex linear system AX = B by LU decomposition
*
'*
*
'*
Basic version by J-P Moreau, Paris *
'*
(www.jpmoreau.fr)
*
'* ------------------------------------------------------------------ *
'* Reference:
*
'*
*
'* "Numerical Recipes by W.H. Press, B. P. Flannery, S.A. Teukolsky *
'* and W.T. Vetterling, Cambridge University Press, 1986."
*
'* ------------------------------------------------------------------ *
'* SAMPLE RUN:
*
'*
*
'* Input file (test_lu.dat):
*
'*
*
'* 15
*
'* 0 0 0 0 6 0 1 0 1 0 4 0 2 0 1 0 2 0 2 0 0 0 3 0 0 0 5 0 0 1 1 1 *
'* 6 0 2 0 5 0 2 0 4 0 5 0 5 0 2 0 1 0 2 0 3 0 1 0 5 0 1 0 3 2 2 2 *
'* 6 0 2 0 5 0 6 0 3 0 6 0 5 0 0 0 0 0 1 0 3 0 0 0 4 0 0 0 5 3 3 3 *
'* 5 0 4 0 3 0 1 0 4 0 4 0 6 0 4 0 6 0 1 0 4 0 2 0 0 0 5 0 3 4 4 4 *
'* 3 0 4 0 6 0 4 0 2 0 0 0 4 0 6 0 5 0 5 0 1 0 1 0 6 0 5 0 4 5 5 5 *
'* 4 0 2 0 0 0 4 0 1 0 6 0 1 0 1 0 3 0 6 0 1 0 1 0 1 0 1 0 4 6 6 6 *
'* 1 0 1 0 4 0 5 0 5 0 0 0 0 0 0 0 0 0 5 0 5 0 2 0 4 0 3 0 5 7 7 7 *
'* 2 0 5 0 5 0 0 0 0 0 0 0 0 0 1 0 4 0 1 0 3 0 1 0 2 0 5 0 2 8 8 8 *
'* 4 0 4 0 6 0 2 0 3 0 2 0 0 0 5 0 5 0 3 0 5 0 2 0 3 0 4 0 6 9 9 9 *
'* 3 0 2 0 0 0 0 0 3 0 4 0 0 0 6 0 5 0 4 0 6 0 1 0 4 0 5 0 3 10 10 10 *
'* 1 0 1 0 6 0 2 0 0 0 6 0 0 0 2 0 0 0 0 0 6 0 3 0 4 0 0 0 4 11 11 11 *
'* 6 0 3 0 2 0 3 0 6 0 2 0 0 0 2 0 3 0 0 0 5 0 5 0 1 0 6 0 3 12 12 12 *
'* 2 0 1 0 5 0 4 0 0 0 4 0 0 0 6 0 3 0 2 0 3 0 1 0 1 0 4 0 6 13 13 13 *
'* 3 0 0 0 5 0 1 0 1 0 6 0 0 0 4 0 3 0 6 0 1 0 0 0 1 0 0 0 2 14 14 14 *
'* 0 0 3 0 3 0 3 0 4 0 5 0 0 0 3 0 1 0 2 0 4 0 6 0 4 0 1 0 4 15 15 15 *
'*
*
'* Output file (test_lu.lst):
*
'* --/-*
'* System solution:
*
'*
*
'* X 1 = -0.057831 0.092402
*
'*
*
'* X 2 = -0.885623 1.415035
*
'*
*
'* X 3 = -0.106641 0.170390
*
'*
*
'* X 4 = -0.421776 0.673908
*
'*
*
'* X 5 = 0.063331 -0.101190
*
'*
*
'* X 6 = -0.098265 0.157007
*
'*
*
'* X 7 = 0.217855 -0.348086
*
'*
*
'* X 8 = -0.698291 1.115719
*
'*
*
'* X 9 = 0.869955 -1.390002
*
'*
*
'* X10 = -0.338608 0.541023
*
'*
*
'* X11 = -0.463159 0.740028
*

'*
*
'* X12 = 0.118877 -0.189941
*
'*
*
'* X13 = 0.514975 -0.822819
*
'*
*
'* X14 = 0.013271 -0.021204
*
'*
*
'* X15 = 0.731170 -1.168252
*
'*
*
'* ------------------------------------------------------------------ *
'* Subroutines used:
*
'* 1000 LUDCMP: LU decomposition of a real square matrix
*
'* 2000 LUBKSB: Solve linear system AX = B, A being the
*
'*
output of LUDCMP.
*
'*
*
'**********************************************************************
DEFINT I-N
DEFDBL A-H, O-Z
CLS :
INPUT
in$ =
ou$ =

PRINT
" Data file name (without .dat): ", nom$
nom$ + ".dat"
nom$ + ".lst"

OPEN in$ FOR INPUT AS #1


OPEN ou$ FOR OUTPUT AS #2
INPUT #1, N

'size of linear system

N1 = N + 1
N2 = N1 * N1
DIM AR(N2), AI(N2), BR(N1), BI(N1), temp(N1, 2), INDX(N1)
'-----------------------------------------------------------------'NOTA: Complex Matrix A of size N+1 x N+1 is stored in txo vectors,
'
line by. AR one for real part and AI for imaginary part.
'
The element (i,j) of the matrix is at location i(n+1) + j in
'
the corresponding vector. The access is faster.
'-----------------------------------------------------------------PRINT
PRINT
PRINT
PRINT
PRINT
PRINT

#2,
#2,
#2,
#2,
#2,
#2,

"--------------------------------------------------"
"
COMPLEX LINEAR SYSTEM TO BE SOLVED:"
"--------------------------------------------------"
" N="; N

FOR I = 1 TO N
FOR J = 1 TO N + 1
INPUT #1, temp(J, 1), temp(J, 2)'read a line
NEXT J
FOR J = 1 TO N
AR(I * (N + 1) + J) = temp(J, 1)
AI(I * (N + 1) + J) = temp(J, 2)
NEXT J
BR(I) = temp(N + 1, 1)
BI(I) = temp(N + 1, 2)
FOR J = 1 TO N + 1
PRINT #2, USING " ###.## ###.##"; temp(J, 1); temp(J, 2);
NEXT J

PRINT #2,
NEXT I
CLOSE #1
GOSUB 1000 'LUDCMP(A,n,INDX,D,CODE)
IF CODE = 0 THEN GOSUB 2000

'LUBKSB(A,n,INDX,B);

IF CODE = 1 THEN
PRINT #2, " The system matrix is singular !"
ELSE
PRINT #2,
PRINT #2, " System solution:"
PRINT #2,
FOR I = 1 TO N
PRINT #2, USING " X## = ##.###### ##.######"; I; BR(I); BI(I)
PRINT #2,
NEXT I
END IF
PRINT #2, "--------------------------------------------------"
PRINT #2, " End of file "; ou$
CLOSE #2
PRINT
PRINT " Results in file "; ou$
PRINT
END 'of main program
'***************************************************************
'* Given an N x N matrix A, this routine replaces it by the LU *
'* decomposition of a rowwise permutation of itself. A and N *
'* are input. INDX is an output vector which records the row *
'* permutation effected by the partial pivoting; D is output *
'* as -1 or 1, depending on whether the number of row inter- *
'* changes was even or odd, respectively. This routine is used *
'* in combination with LUBKSB to solve linear equations or to *
'* invert a matrix. Return code is 1, if matrix is singular. *
'***************************************************************
1000 'SUBROUTINE LUDCMP FOR COMPLEX MATRIX
NMAX = 100: TINY = 2.2E-16
DIM VV(N, 2), AMAX(2), SUM(2), DUM(2), TMP(2), TMP1(2)
D = 1: CODE = 0
FOR I = 1 TO N
AMAX(1) = 0#: AMAX(2) = 0#
FOR J = 1 TO N
IF CABS(AR(I * N1 + J), AI(I * N1 + J)) > CABS(AMAX(1), AMAX(2)) THEN
AMAX(1) = AR(I * N1 + J)
AMAX(2) = AI(I * N1 + J)
END IF
NEXT J
IF CABS(AMAX(1), AMAX(2)) < TINY THEN
CODE = 1
RETURN
END IF
'

VV(I) = 1.0 / AMAX

TMP(1) = 1#: TMP(2) = 0#


CDIV TMP(), AMAX(), DUM()
VV(I, 1) = DUM(1): VV(I, 2) = DUM(2)
NEXT I 'i loop
FOR J = 1 TO N
FOR I = 1 TO J - 1
SUM(1) = AR(I * N1 + J)
SUM(2) = AI(I * N1 + J)
FOR K = 1 TO I - 1
'
SUM = SUM - A(I * N1 + K) * A(K * N1 + J)
TMP(1) = AR(I * N1 + K): TMP(2) = AI(I * N1 + K)
TMP1(1) = AR(K * N1 + J): TMP1(2) = AI(K * N1 + J)
CMUL TMP(), TMP1(), DUM()
SUM(1) = SUM(1) - DUM(1)
SUM(2) = SUM(2) - DUM(2)
NEXT K
AR(I * N1 + J) = SUM(1)
AI(I * N1 + J) = SUM(2)
NEXT I 'i loop
AMAX(1) = 0#: AMAX(2) = 0#
FOR I = J TO N
SUM(1) = AR(I * N1 + J)
SUM(2) = AI(I * N1 + J)
FOR K = 1 TO J - 1
'
SUM = SUM - A(I * N1 + K) * A(K * N1 + J)
TMP(1) = AR(I * N1 + K): TMP(2) = AI(I * N1 + K)
TMP1(1) = AR(K * N1 + J): TMP1(2) = AI(K * N1 + J)
CMUL TMP(), TMP1(), DUM()
SUM(1) = SUM(1) - DUM(1)
SUM(2) = SUM(2) - DUM(2)
NEXT K
AR(I * N1 + J) = SUM(1)
AI(I * N1 + J) = SUM(2)
'
DUM = VV(I) * ABS(SUM)
DUM(1) = VV(I, 1) * CABS(SUM(1), SUM(2))
DUM(2) = VV(I, 2) * CABS(SUM(1), SUM(2))
IF CABS(DUM(1), DUM(2)) >= CABS(AMAX(1), AMAX(2)) THEN
IMAX = I
AMAX(1) = DUM(1): AMAX(2) = DUM(2)
END IF
NEXT I 'i loop
IF J <> IMAX THEN
FOR K = 1 TO N
DUM(1) = AR(IMAX * N1 + K)
DUM(2) = AI(IMAX * N1 + K)
AR(IMAX * N1 + K) = AR(J * N1 + K)
AI(IMAX * N1 + K) = AI(J * N1 + K)
AR(J * N1 + K) = DUM(1)
AI(J * N1 + K) = DUM(2)
NEXT K 'k loop
D = -D
VV(IMAX, 1) = VV(J, 1)
VV(IMAX, 2) = VV(J, 2)
END IF
INDX(J) = IMAX
IF CABS(AR(J * N1 + J), AI(J * N1 + J)) < TINY THEN
AR(J * N1 + J) = TINY

AI(J * N1 + J) = 0#
END IF
IF J <> N THEN
DUM = 1# / A(J * N1 + J)
TMP(1) = 1#: TMP(2) = 0#
TMP1(1) = AR(J * N1 + J): TMP1(2) = AI(J * N1 + J)
CDIV TMP(), TMP1(), DUM()
FOR I = J + 1 TO N
'
A(I * N1 + J) = A(I * N1 + J) * DUM
TMP(1) = AR(I * N1 + J): TMP(2) = AI(I * N1 + J)
CMUL TMP(), DUM(), TMP1()
AR(I * N1 + J) = TMP1(1)
AI(I * N1 + J) = TMP1(2)
NEXT I
END IF
NEXT J 'j loop
'

RETURN 'subroutine LUDCMP


'******************************************************************
'* Solves the set of N linear equations A . X := B. Here A is
*
'* input, not as the matrix A but rather as its LU decomposition, *
'* determined by the routine LUDCMP. INDX is input as the permuta-*
'* tion vector returned by LUDCMP. B is input as the right-hand *
'* side vector B, and returns with the solution vector X. A, N and*
'* INDX are not modified by this routine and can be used for suc- *
'* cessive calls with different right-hand sides. This routine is *
'* also efficient for plain matrix inversion.
*
'******************************************************************
2000 'SUBROUTINE LUBKSB
II = 0: N1 = N + 1
FOR I = 1 TO N
LL = INDX(I)
SUM(1) = BR(LL): SUM(2) = BI(LL)
BR(LL) = BR(I): BI(LL) = BI(I)
IF II <> 0 THEN
FOR J = II TO I - 1
'
SUM = SUM - A(I * N1 + J) * B(J)
TMP(1) = AR(I * N1 + J): TMP(2) = AI(I * N1 + J)
TMP1(1) = BR(J): TMP1(2) = BI(J)
CMUL TMP(), TMP1(), DUM()
SUM(1) = SUM(1) - DUM(1)
SUM(2) = SUM(2) - DUM(2)
NEXT J
ELSEIF CABS(SUM(1), SUM(2)) <> 0 THEN
II = I
END IF
BR(I) = SUM(1): BI(I) = SUM(2)
NEXT I 'i loop
FOR I = N TO 1 STEP -1
SUM(1) = BR(I): SUM(2) = BI(I)
IF I < N THEN
FOR J = I + 1 TO N
'
SUM = SUM - A(I * N1 + J) * B(J)
TMP(1) = AR(I * N1 + J): TMP(2) = AI(I * N1 + J)
TMP1(1) = BR(J): TMP1(2) = BI(J)
CMUL TMP(), TMP1(), DUM()

SUM(1) = SUM(1) - DUM(1)


SUM(2) = SUM(2) - DUM(2)
NEXT J
END IF
' B(I) = SUM / A(I * N1 + I)
TMP(1) = AR(I * N1 + I): TMP(2) = AI(I * N1 + I)
CDIV SUM(), TMP(), DUM()
BR(I) = DUM(1): BI(I) = DUM(2)
NEXT I 'i loop
RETURN
FUNCTION CABS (X, Y)
CABS = SQR(X * X + Y * Y)
END FUNCTION
SUB CDIV (Z1(), Z2(), Z())
DIM C1(2)
D = Z2(1) ^ 2 + Z2(2) ^ 2
IF D < 2.2E-16 THEN
PRINT #2, " Complex Divide by zero!"
ELSE
C1(1) = Z2(1): C1(2) = -Z2(2)
CMUL Z1(), C1(), Z()
Z(1) = Z(1) / D: Z(2) = Z(2) / D
END IF
END SUB
SUB CMUL (Z1(), Z2(), Z())
Z(1) = Z1(1) * Z2(1) - Z1(2) * Z2(2)
Z(2) = Z1(1) * Z2(2) + Z1(2) * Z2(1)
END SUB

Vous aimerez peut-être aussi