1 ' MATRIX OPERATIONS --- MATOP.BAS --- by Dr Russell Langley
2 GOTO 400
4 '<UNK! {000A}>--- Press Enter ---
5 IF PR THEN RETURN ELSE PRINT TAB(40);:PRINT "Press <Enter> to continue.";:IN$=INKEY$:WHILE INKEY$<>CHR$(13):WEND:LOCATE,40:PRINT SPACE$(26):RETURN
7 '<UNK! {000A}>*** Redirect to Block ***
9 ON QB GOTO 10,177,429,409,488:STOP '=start,printout,etc - CLOSE (exc 177)<UNK! {000A}><UNK! {000A}>--- Another go? ---
10 CLOSE:IF HEAD=1 THEN LPRINT STRING$(79,61)STRING$(4,10)
11 DO$="run this program again now":GOSUB 20:IF Z$="Y" THEN 2 ELSE 30
19 '<UNK! {000A}>--- Yes/No? ---
20 PRINT:PRINT"Do you want to "+DO$;
21 INPUT" (Y/N)";Z$:IF Z$="" THEN Z$="N":RETURN ELSE Z$=CHR$(ASC(Z$) AND 95):IF Z$="Y" OR Z$="N" THEN RETURN ELSE PRINT"WHAT? ";:GOTO 21
29 '<UNK! {000A}>--- Errors & End ---
30 IF ERR THEN BEEP ELSE RUN "MENU"
31 IF ERR=70 THEN LINE INPUT"Can't write to that disk. Remove its Write-Protect tab, then press <Enter>.";Z$:RESUME
32 IF ERR=71 THEN LINE INPUT"That drive is empty or its gate is open. Fix, then press <Enter>.";Z$:RESUME
33 IF ERR=210 THEN RESUME 9 'from #86
39 ON ERROR GOTO 0:END'<UNK! {000A}><UNK! {000A}>--- Messages ---
40 BEEP:PRINT "---> Sorry, that entry is illegal.":RETURN
41 BEEP:PRINT "---> Sorry, double quotes are not allowed here.":RETURN
42 BEEP:PRINT"* * * Can't Do That.":QB=4:GOTO 9
43 COLOR 23,0:PRINT:PRINT"Working";:COLOR 7,0:LOCATE ,1:RETURN
44 LOCATE,1:PRINT"Ok, done.";:GOTO 5
46 ZZ$=STRING$(37-LEN(Z$)\2,177):LOCATE 1,1:PRINT ZZ$" ";:COLOR 15,0:PRINT Z$;:COLOR 7,0:PRINT" "ZZ$:RETURN 'Display brightened Z$ at top of screen
49 '<UNK! {000A}>*** Vetted Decoding of FF ..C(I,J).. from X$ ***<UNK! {000A}> Needs I, M, Q(0) from #96 or #256, & UT>0 if UT matrix.
50 K=1:L=M:IF UT>0 THEN L=M-I+1
51 KX=0:FOR J=K TO L:Y$=SPACE$(10):KY=0
52 KX=KX+1:IF KX>LEN(X$) THEN IF J=L THEN 54 ELSE 57
53 Z$=MID$(X$,KX,1):IF INSTR("-.0123456789",Z$) THEN KY=KY+1:MID$(Y$,KY,1)=Z$:GOTO 52 ELSE IF Z$<>" " THEN 58 ELSE IF KY=0 THEN 52
54 IF Q(0) THEN Q(J)=VAL(Y$) ELSE C(I,J)=VAL(Y$)
55 NEXT J:IF KX>=LEN(X$) THEN 60
56 PLAY"L8O3CO2C":PRINT"Only the first"L"values have been read in that line. Re-do it";:GOSUB 21:IF Z$="Y" THEN 59 ELSE 60
57 PLAY"L32O4CEG>C":PRINT"Not enough values in the line above. Please re-do whole line.":GOTO 59
58 PLAY"L16O3CEL4>B":PRINT"That line contains a `non-numeric' entry. Please re-do whole line."
59 INPUT X$:IF RIGHT$(X$,1)<>"/" THEN 51 ELSE X$=LEFT$(X$,LEN(X$)-1):N=I+(X$=""):IF X$>"" THEN 51
60 RETURN
69 '<UNK! {000A}>--- K/b Input of all X(I,J) in FF ---<UNK! {000A}> Needs first I, M, & if UT matrix UT>0. Returns N.
70 PRINT"Enter data from keyboard, ";:IF M=1 THEN PRINT "pressing <Enter> after each number.":GOTO 72
71 PRINT"in Free Format, pressing <Enter> at end of each row.":IF UT>0 THEN 73
72 PRINT"Null entry duplicates previous row. Signal `end-of-data' by entering a `/'"
73 PRINT "Row"STR$(I);:INPUT X$:IF UT>0 AND I=M THEN N=M:GOTO 75 ELSE IF X$=""THEN IF I>1 THEN FOR J=1 TO M:X(I,J)=X(I-1,J):NEXT J:I=I+1:LOCATE CSRLIN-1,POS(0)+9:PRINT"Ditto":GOTO 73
74 IF RIGHT$(X$,1)="/" THEN X$=LEFT$(X$,LEN(X$)-1):N=I+(X$=""):IF X$="" THEN 76
75 GOSUB 50:IF N=0 THEN IF I<MXR THEN I=I+1:GOTO 73 ELSE N=MXR
76 RETURN
79 '<UNK! {000A}>*** Disk Input of C(I,J), N, M, etc ***
80 QD=1:IO$="I":GOSUB 110:CLS:PRINT "Loading data from disk.":INPUT #1,FL$,VR$
81 IF LEFT$(VR$,4)<>"(RL," THEN BEEP:PRINT "Unreadable file --- not made by our Data Filer/Editor program.":GOTO 86
83 PRINT"File has"N"rows of data.":IF N>MXR THEN PRINT"--- Too many!":GOTO 85
84 PRINT:PRINT"File has"M"column variables.":IF M>MXC THEN PRINT"--- Too many!" ELSE IF ABS(UT)<=1 THEN 86 ELSE PRINT"This matrix based on"ABS(UT)"persons.":GOTO 86
85 CLOSE:BEEP:GOSUB 5:ERROR 210
86 IF MT=2 THEN 476 'test legality of B before proceeding.
87 ' Select variables
88 PRINT:IF VN$="N" THEN PRINT "The"M"variables are not named.":GOTO 90
89 PRINT "Variables in file are:":FOR J=1 TO M:INPUT #1,VN$(J):PRINT J;VN$(J),:NEXT J:PRINT
90 IF M=MNC OR UT>0 THEN 100 ELSE PRINT
91 PRINT"How many filed column variables are to be IGNORED (0-"MID$(STR$(M-MNC),2)")";:INPUT ND:IF ND<0 OR ND>M-MNC THEN 91 ELSE IF ND=0 THEN 100
92 '
93 '
94 IF ND=1 THEN PRINT "Number of the variable to be IGNORED (1-"MID$(STR$(M),2)")";:INPUT X$:Q(1)=VAL(X$):IF Q(1)<1 OR Q(1)>M THEN GOSUB 40:GOTO 94 ELSE 97
95 PRINT MID$(STR$(ND),2)" numbers of variables to be IGNORED (in ascending order & Free Format):":INPUT X$:IF VAL(X$)<1 THEN GOSUB 40:GOTO 95
96 Q(0)=1:MM=M:M=ND:GOSUB 50:Q(0)=0:M=MM
97 KK=1:L=1:FOR J=1 TO M:IF J=Q(KK) THEN KK=KK+1 ELSE VN$(L)=VN$(J):L=L+1
98 NEXT J
99 ' Now read numerical data from disk
100 COLOR 23,0:PRINT"Loading numbers";:COLOR 7,0:FOR I=1 TO N:KK=1:LL=1:IF UT<=0 THEN L=M ELSE L=M-I+1
101 FOR J=1 TO L:INPUT #1,Z
102 IF J=Q(KK) THEN KK=KK+1 ELSE C(I,LL)=Z:LL=LL+1
103 NEXT J:NEXT I:CLOSE:LOCATE,1:M=M-ND:RETURN
109 '<UNK! {000A}>--- Get Filespec ---
110 IF IO$="O" AND FL$>"" THEN PRINT "Will you file this data under the name "FL$;:GOSUB 21:IF Z$="Y" THEN 115
111 LINE INPUT "Filename (I will add .DAT extension)? ";FL$:IF FL$="" THEN 111 ELSE IF MID$(FL$,2,1)=":" THEN DR$=LEFT$(FL$,1):FL$=MID$(FL$,3)
112 ER=0:FOR I=1 TO LEN(FL$):Z$=MID$(FL$,I,1):IF INSTR(" .,/\|?*:;[]+="+CHR$(34),Z$) THEN ER=1
113 NEXT I
114 IF ER=0 AND FL$>"" AND LEN(FL$)<9 THEN FL$=FL$+".DAT" ELSE BEEP:PRINT "Invalid filename. Will you try again";:GOSUB 21:IF Z$="Y" THEN 111 ELSE 2
115 INPUT "Which drive (A,B,C,D)";DR$:IF DR$="" THEN 115
116 DR$=CHR$(ASC(DR$) AND 95):IF INSTR("ABCD",DR$)=0 THEN 115
117 INPUT "Which directory (e.g. WORK, MYDATA, or Null Entry if root) ";DR2$:IF DR2$="" THEN DR$=DR$+":" ELSE DR$=DR$+":\"+DR2$+"\"
129 '<UNK! {000A}>--- Open File, IO$= "I" or "O" ---
130 IF IO$="I" THEN 134 ELSE ON ERROR GOTO 132:OPEN DR$+FL$ FOR INPUT AS #1
131 CLOSE:DO$="<OVERWRITE> existing "+FL$:GOSUB 20:IF Z$="N" THEN 110 ELSE 133
132 RESUME 133 'OK to start new file, since FL$ not present.
133 ON ERROR GOTO 30:OPEN DR$+FL$ FOR OUTPUT AS #1:RETURN 'print #1,Q$A$Q$Q$B$Q$:close
134 ON ERROR GOTO 136:OPEN DR$+FL$ FOR INPUT AS #1 'for input
351 I=23:J=42:PRINT"1 A'"TAB(I)"7 A * k"TAB(J)"13 A' * B(Inv) * A<UNK! {000A}>2 A * A'"TAB(I)"8 A / k"TAB(J)"14 Normalize<UNK! {000A}>3 A(Inv)"TAB(I)"9 A * B"TAB(J)"15 Sqrt Diag Any Square A"
352 I=22:PRINT"4 A + B"TAB(I)"10 B * A"TAB(J)"16 Inv Sqrt Diag Any Square A<UNK! {000A}>5 A - B"TAB(I)"11 A * B(Inv)"TAB(J)"17 Eigenstructure Symmetric A<UNK! {000A}>6 B - A"TAB(I)"12 A' * B * A"TAB(J)"18 Eigenstructure B(Inv) * A":PRINT:RETURN
430 DO$="enter "+CHR$(34)+M$(MT)+CHR$(34)+" from Disk":GOSUB 20:IF Z$="N" THEN 434
431 '<UNK! {000A}>--- Disk Entry ---
432 QB=3:GOSUB 80:GOSUB 5:GOTO 441
433 '<UNK! {000A}>--- Keyboard Entry ---
434 QB=3:QD=0:I=0:M=2:UT=0:PRINT"# of Rows & # of Cols in "M$(MT)" (Free Format, both max "MID$(STR$(MXC),2)")";:INPUT X$:GOSUB 50:N=C(0,1):M=C(0,2):IF N<1 OR N>MXR OR M<1 OR M>MXC THEN BEEP:PRINT"Size out of bounds!":GOTO 434
435 IF MT=1 THEN NA=N:MA=M ELSE NB=N:MB=M:GOTO 476
436 I=1:IF N=M THEN PRINT U$"Matrix";:GOSUB 21:IF Z$="Y" THEN 438
437 UT=0:PRINT"Enter "M$(MT)L$:GOTO 439
438 UT=1:PRINT"Enter "U$M$(MT)L$
439 PRINT"Row"I;:INPUT X$:GOSUB 50:IF I<N THEN I=I+1:GOTO 439
440 '<UNK! {000A}>--- Show Matrix ---
441 QB=4:GOSUB 160:PRINT #2,
442 IF QR=0 THEN PRINT #2,M$(MT);" was read as:" ELSE PRINT #2,"Revised ";M$(MT);" is:"
443 MM=M:L=1:FOR I=1 TO N:PRINT #2,USING R$;I,:LN=0:JJ=9:IF UT>0 THEN MM=M-I+1:IF QD=1 THEN JJ=4
444 J1=1+LN*(JJ+1):J2=-(MM<J1+JJ)*MM-(MM>=J1+JJ)*(J1+JJ):FOR J=J1 TO J2:PRINT #2,C(I,J);:NEXT J:PRINT #2,:L=L+1:IF L>19 THEN GOSUB 5:L=0
445 IF MM>J2 THEN LN=LN+1:PRINT #2,SPACE$(9);:GOTO 444
446 NEXT I:PRINT #2,:IF PR=1 THEN RETURN
447 '<UNK! {000A}>--- Edit Matrix ---
448 PRINT"Any data changes";:GOSUB 21:IF Z$="N" THEN 458
449 IF N=1 THEN I=1:GOTO 451
450 INPUT"Which row";I:IF I<1 OR I>N THEN PRINT"Silly.":GOTO 450
451 IF UT>0 THEN L=M-I+1 ELSE L=M
452 PRINT USING R$;I;:FOR J=1 TO L:PRINT C(I,J);:NEXT J:PRINT
453 QR=1:IF L=1 THEN INPUT"Right value";C(I,L):GOTO 441
454 PRINT"Change which variable # (1-"MID$(STR$(L),2)") ";:INPUT Z$:J=VAL(Z$):IF J<1 OR J>L THEN BEEP:PRINT"What ?":GOTO 454
455 PRINT"Old value =";C(I,J);TAB(28);"New value";:INPUT Z$:FOR K=1 TO LEN(Z$):IF INSTR("-.0123456789",MID$(Z$,K,1)) THEN NEXT K:C(I,J)=VAL(Z$) ELSE PLAY"L16O3CEL4>B":PRINT"That contains a `non-numeric' entry. Please re-do.":GOTO 455
456 GOTO 441
457 '<UNK! {000A}>--- Print Data? ---
458 DO$="print this data":GOSUB 20:IF Z$="N" THEN 461
459 GOSUB 162:GOSUB 165:GOSUB 442:GOSUB 160
460 '<UNK! {000A}>--- Copy C into A or B ---
461 CLS:QR=0:IF UT>0 THEN 465 ELSE ON MT GOTO 462,463
462 FOR I=1 TO N:FOR J=1 TO M:A(I,J)=C(I,J):NEXT J:NEXT I:GOTO 470
463 FOR I=1 TO N:FOR J=1 TO M:B(I,J)=C(I,J):NEXT J:NEXT I:GOTO 481
464 ' First assign UTM values to their proper subscripts.
465 FOR I=2 TO M:FOR J=M TO I STEP -1:C(I,J)=C(I,J-I+1):NEXT J:NEXT I:ON MT GOTO 467,468
466 ' Now expand UTM to full matrices, C and A or B.
467 FOR I=1 TO M:FOR J=I TO M:C(J,I)=C(I,J):A(I,J)=C(I,J):A(J,I)=A(I,J):NEXT J:NEXT I:GOTO 470
468 FOR I=1 TO M:FOR J=I TO M:C(J,I)=C(I,J):B(I,J)=C(I,J):B(J,I)=B(I,J):NEXT J:NEXT I:GOTO 481
472 ON OP GOTO 490,492,475,473,473,473,504,504,473,473,473,473,473,529,475,475,475,473:GOTO 471
473 MT=2:GOTO 430
474 '<UNK! {000A}>--- Test Legality ---
475 IF NA<>MA THEN BEEP:PRINT E$M$(1)NS$:GOTO 471 ELSE IF OP=3 THEN 494 ELSE ON (OP-14) GOTO 533,538,543
476 ON OP GOTO 2,2,2,477,477,477,2,2,478,479,478,479,479,2,2,2,2,479
477 IF NA<>NB OR MA<>MB THEN PRINT E$NC$:GOTO 430 ELSE 480
478 IF MA<>NB THEN PRINT E$NC$:GOTO 430 ELSE IF OP=9 THEN 480 ELSE IF NB<>MB THEN PRINT E$M$(2)NS$:GOTO 430 ELSE 480
479 IF NA<>MB THEN PRINT E$NC$:GOTO 430 ELSE IF OP=10 THEN 480 ELSE IF NB<>MB THEN PRINT E$M$(2)NS$:GOTO 430
480 IF QD=0 THEN 436 ELSE ON MT GOTO 441,88 'Continue data entry from disk if B.
481 GOSUB 43:ON OP GOTO 2,2,2,498,500,502,2,2,510,514,516,520,525,2,2,2,2,552
482 '<UNK! {000A}>--- Finale ---
483 DO$="file this matrix":GOSUB 20:IF Z$="N" THEN 487
484 INPUT "How many vectors of measurements contributed to this matrix";UT:IF UT<1 THEN BEEP:GOTO 484
485 IF VN$="" THEN VN$="N"
486 UT=-UT:GOSUB 140 'hold # persons as -ut, then file full matrix (not UTM).
487 PRINT:PRINT"Another operation on ";:COLOR 23,0:PRINT"this";:COLOR 7,0:PRINT" matrix";:GOSUB 21:IF Z$="Y" THEN 470 ELSE IF HEAD=1 THEN HEAD=0:LPRINT STRING$(79,61)STRING$(4,10)
488 CLOSE:BEEP:PRINT:PRINT"===> ANOTHER MATRIX PROBLEM";:GOSUB 21:IF Z$="Y" THEN CLS:GOTO 429 ELSE 30
489 ' ------------------- Operations -------------------<UNK! {000A}><UNK! {000A}>--1 A'
490 FOR I=1 TO N:FOR J=1 TO M:C(J,I)=A(I,J):NEXT J:NEXT I:SWAP NA,MA:N=NA:M=MA:FOR I=1 TO N:FOR J=1 TO M:A(I,J)=C(I,J):NEXT J:NEXT I
491 PRINT #2,"TRANSPOSE, A'"EQA$:GOSUB 564:IF PR=1 THEN 491 ELSE 483'<UNK! {000A}><UNK! {000A}>--2 A * A'
492 GOSUB 43:FOR I=1 TO N:FOR J=1 TO N:C(I,J)=0:FOR K=1 TO M:C(I,J)=C(I,J)+A(I,K)*A(J,K):NEXT K:NEXT J:NEXT I:MA=NA:M=MA:FOR I=1 TO N:FOR J=1 TO M:A(I,J)=C(I,J):NEXT J:NEXT I
507 PRINT #2,:PRINT #2,"With k ="STR$(C)", SCALED MATRIX A ";:RETURN'<UNK! {000A}><UNK! {000A}>--8 A / k
508 FOR I=1 TO N:FOR J=1 TO M:A(I,J)=A(I,J)/C:NEXT J:NEXT I
509 GOSUB 507:PRINT #2,"/ k"EQA$:GOSUB 564:IF PR=1 THEN 509 ELSE 483'<UNK! {000A}><UNK! {000A}>--9 A * B
510 FOR I=1 TO NA:FOR J=1 TO MB:C(I,J)=0:FOR K=1 TO MA:C(I,J)=C(I,J)+A(I,K)*B(K,J):NEXT K:NEXT J:NEXT I:N=NA:MA=MB:M=MA:FOR I=1 TO N:FOR J=1 TO M:A(I,J)=C(I,J):NEXT J:NEXT I
513 PRINT #2,P$"A * B(Inv)"EQA$:GOSUB 564:IF PR=1 THEN 513 ELSE 483'<UNK! {000A}><UNK! {000A}>--10 B * A
514 FOR I=1 TO NB:FOR J=1 TO MA:C(I,J)=0:FOR K=1 TO MB:C(I,J)=C(I,J)+B(I,K)*A(K,J):NEXT K:NEXT J:NEXT I:NA=NB:N=NA:M=MA:FOR I=1 TO N:FOR J=1 TO M:A(I,J)=C(I,J):NEXT J:NEXT I
515 PRINT"REVERSE "P$"B * A"EQA$:GOSUB 564:IF PR=1 THEN 513 ELSE 483'<UNK! {000A}><UNK! {000A}>--11 A * B(Inv)
516 M=NB:FOR I=1 TO M:FOR J=1 TO M:D(I,J)=B(I,J):NEXT J:NEXT I:GOSUB 574:GOSUB 160
529 NA=N:MA=M:GOSUB 160:IF N>1 THEN 531 ELSE S=0:FOR J=1 TO M:S=S+A(1,J)*A(1,J):NEXT J:S=SQR(S):FOR J=1 TO M:A(1,J)=A(1,J)/S:NEXT J
530 PRINT #2,"NORMALIZED VECTOR"EQA$:GOSUB 564:IF PR=1 THEN 530 ELSE 483
531 FOR J=1 TO M:E(J)=0:FOR I=1 TO N:E(J)=E(J)+A(I,J)*A(I,J):NEXT I:NEXT J:FOR J=1 TO M:E(J)=SQR(E(J)):FOR I=1 TO N:A(I,J)=A(I,J)/E(J):NEXT I:NEXT J:IF M=1 THEN 530
532 PRINT #2,"NORMALIZED MATRIX"EQA$:GOSUB 564:IF PR=1 THEN 532 ELSE 483'<UNK! {000A}><UNK! {000A}>--15 Sqrt Diag A
533 FOR I=1 TO N:FOR J=1 TO M:IF I<>J THEN A(I,J)=0:GOTO 535 'diagonalize the matrix.
534 IF A(I,I)>=0 THEN A(I,I)=SQR(A(I,I)) ELSE FLAG=I:I=N:J=M
535 NEXT J:NEXT I:IF FLAG>0 THEN 537 ELSE GOSUB 160
536 PRINT #2,"SQRT OF DIAGONAL A"EQA$:GOSUB 564:IF PR=1 THEN 536 ELSE 483
537 BEEP:PRINT"Can't SQRT, because diagonal element"FLAG"is negative.":FLAG=0:GOTO 488'<UNK! {000A}><UNK! {000A}>--16 Inv Sqrt Diag A
538 FOR I=1 TO N:FOR J=1 TO M:IF I<>J THEN A(I,J)=0:GOTO 541 'diagonalize the matrix.
539 IF A(I,I)<0 THEN FLAG=I:I=N:J=M:GOTO 541 ELSE IF A(I,I)<1E-10 THEN A(I,I)=0
540 A(I,I)=1/SQR(A(I,I))
541 NEXT J:NEXT I:IF FLAG>0 THEN 537 ELSE GOSUB 160
542 PRINT #2,"INVERSE SQRT OF DIAGONAL A"EQA$:GOSUB 564:IF PR=1 THEN 542 ELSE 483'<UNK! {000A}><UNK! {000A}>--17 Eigen Symmetric A
543 IF M=2 THEN NV=2 ELSE EMIN=M:PRINT"How many Eigenvalues required (2-"MID$(STR$(M),2)"), or Min Value (less than 2)";:INPUT EMIN:IF EMIN>M THEN 543 ELSE IF EMIN<2 THEN NV=M ELSE NV=EMIN
544 GOSUB 43:TR=0:FOR I=1 TO M:TR=TR+A(I,I):NEXT I:GOSUB 599:CLS:GOSUB 160
545 PRINT #2,D$M$(MT)" = ";:IF NV<M THEN PRINT #2,"?" ELSE D=1:FOR I=1 TO M:D=D*E(I):NEXT I:PRINT #2,D
546 PRINT #2,"EIGENVALUES ";:S=0:Q=0:IF OP=18 THEN PRINT #2,"=":T$=LEFT$(P$,7):GOTO 548
547 T$="A":IF M=2 THEN PRINT #2,"=" ELSE IF EMIN<2 THEN PRINT #2,"(No. determined by MIN VALUE ="STR$(EMIN)"):" ELSE PRINT #2,"("MID$(STR$(NV),2)" values, as requested) ="
548 IF PR=0 THEN GOSUB 160
549 GOSUB 559:PRINT #2,"SUM OF EIGENVALUES = "S" TRACE OF "T$" = "TR:PRINT #2,:GOSUB 5
550 PRINT #2,"NORMALIZED EIGENVECTORS (columnwise)"EQA$:N=NA:M=NV:MA=M:Q=1:GOSUB 559:FOR I=1 TO N:FOR J=1 TO M:A(I,J)=V(I,J):NEXT J:NEXT I
551 GOSUB 570:IF PR=1 THEN 545 ELSE 483'<UNK! {000A}><UNK! {000A}>--18 Eigen B(Inv) * A
552 M=MA:FOR I=1 TO NA:FOR J=1 TO M:C(I,J)=A(I,J):NEXT J:NEXT I:GOSUB 574:DA=D:FOR I=1 TO NB:FOR J=1 TO MB:C(I,J)=B(I,J):NEXT J:NEXT I:GOSUB 574:DB=D
553 FOR I=1 TO NA:FOR J=1 TO M:V(I,J)=0:FOR K=1 TO M:V(I,J)=V(I,J)+C(I,K)*A(K,J):NEXT K:NEXT J:NEXT I
574 D=1:FLAG=0:FOR I=1 TO M:IP(I)=0:NEXT I:FOR I=1 TO M:Z=0:FOR J=1 TO M:IF IP(J)=1 THEN 579
575 FOR K=1 TO M:ON SGN(IP(K)-1)+2 GOTO 577,578,576
576 I=M:J=M:K=M:FLAG=1:GOTO 578
577 IF Z < ABS(C(J,K)) THEN IR=J:IC=K:Z=C(J,K)
578 NEXT K
579 NEXT J:IF FLAG=1 THEN 585
580 IP(IC)=IP(IC)+1:IF IR<>IC THEN D=-D:FOR L=1 TO M:Z=C(IR,L):C(IR,L)=C(IC,L):C(IC,L)=Z:NEXT L
581 KR(I)=IR:KC(I)=IC:P(I)=C(IC,IC):D=D*P(I):IF ABS(P(I))<=9.99E-07 THEN D=0:I=M:GOTO 585
582 C(IC,IC)=1:FOR L=1 TO M:C(IC,L)=C(IC,L)/P(I):NEXT L
583 FOR K=1 TO M:IF K<>IC THEN Z=C(K,IC):C(K,IC)=0:FOR L=1 TO M:C(K,L)=C(K,L)-C(IC,L)*Z:NEXT L
584 NEXT K
585 NEXT I:IF FLAG=1 OR D=0 THEN 589
586 FOR I=1 TO M:Q=M-I+1:IF KR(Q)=KC(Q) THEN 588 ELSE K=KR(Q):L=KC(Q)
587 FOR J=1 TO M:Z=C(J,K):C(J,K)=C(J,L):C(J,L)=Z:NEXT J
588 NEXT I
589 ' Verify inverse
590 FOR I=1 TO M:FOR J=1 TO M:V(I,J)=0:FOR K=1 TO M:V(I,J)=V(I,J)+D(I,K)*C(K,J):NEXT K:NEXT J:NEXT I:FOR I=1 TO M:FOR J=1 TO M:V(I,J)=ABS(V(I,J)):NEXT J:NEXT I
591 IF ABS(D) < 9.99E-07 THEN D=0
592 RETURN
593 '<UNK! {000A}>--- Print C*C(Inv) ---
594 IF OP=3 THEN X$="A*A(Inv)" ELSE X$="B*B(Inv)":IF OP=13 THEN M=NB
595 GOSUB 572:PRINT #2,"Above results are Ok if the following "X$" product is an Identity Matrix:"
596 FOR I=1 TO M:FOR J=1 TO M:PRINT #2,USING"###.##";V(I,J);:NEXT J:PRINT #2,:GOSUB 572:NEXT I:IF PR=1 THEN PRINT #2,
597 GOSUB 570:IF PR=1 THEN 495 ELSE 483
598 '<UNK! {000A}>--- Sub HOW - (Householder, Ortega & Wilkinson, after W W Cooley & P R Lohnes)<UNK! {000A}> Input = C(I,J), M, MD, NV, EMIN. Output = V(I,J), E(I), NV.
599 FOR I=1 TO M:FOR J=1 TO M:R(I+(J-1)*MD)=C(I,J):NEXT J:NEXT I 'Equates uni-dimensional R(I) with C(I,J).
600 IF EMIN<2 THEN EIG=EMIN ELSE EIG= -1E+20
601 '<UNK! {000A}> Tri-diagonalize.
602 M1=M-1:M2=M1*MD+M:M3=M2-MD:M4=MD+1:L=0:FOR I=1 TO M2 STEP M4:L=L+1:AA(L)=R(I):NEXT I:BB(1)=0:IF M=2 THEN 614 ELSE KK=0
603 FOR K=2 TO M1:KL=KK+K:KU=KK+M:KJ=K+1:SUM=0
604 FOR J=KL TO KU:SUM=SUM+R(J)*R(J):NEXT J:S=SQR(SUM):Z=R(KL):IF Z>0 THEN BB(K)=-S ELSE BB(K)=S
605 S=1/S:CC(K)=SQR(ABS(Z)*S+1):R(KL)=CC(K):X=ABS(S/CC(K)):IF Z<0 THEN X=-X
606 FOR I=KJ TO M:JJ=I+KK:CC(I)=X*R(JJ):R(JJ)=CC(I):NEXT I
607 FOR J=K TO M:JJ=J+1:DD(J)=0:L=KK+J
608 FOR I=K TO J:L=L+MD:DD(J)=DD(J)+R(L)*CC(I):NEXT I:IF J=M THEN 610
609 FOR I=JJ TO M:L=L+1:DD(J)=DD(J)+R(L)*CC(I):NEXT I
610 NEXT J:X=0:FOR J=K TO M:X=X+CC(J)*DD(J):NEXT J:X=0.5*X:FOR I=K TO M:DD(I)=X*CC(I)-DD(I):NEXT I:LL=KK:KK=KK+MD
611 FOR I=K TO M:LL=LL+MD:FOR J=I TO M:L=LL+J:R(L)=R(L)+DD(I)*CC(J)+DD(J)*CC(I):NEXT J:NEXT I
612 NEXT K:L=1:FOR I=1 TO M:X=AA(I):AA(I)=R(L):R(L)=X:L=L+M4:NEXT I