2
SUBROUTINE LA05AS (A, IND, NZ, IA, N, IP, IW, W, G, U)
3
C***BEGIN PROLOGUE LA05AS
5
C***PURPOSE Subsidiary to SPLP
7
C***TYPE SINGLE PRECISION (LA05AS-S, LA05AD-D)
11
C THIS SUBPROGRAM IS A SLIGHT MODIFICATION OF A SUBPROGRAM
12
C FROM THE C. 1979 AERE HARWELL LIBRARY. THE NAME OF THE
13
C CORRESPONDING HARWELL CODE CAN BE OBTAINED BY DELETING
14
C THE FINAL LETTER =S= IN THE NAMES USED HERE.
15
C REVISIONS MADE BY R J HANSON, SNLA, AUGUST, 1979.
16
C REVISED SEP. 13, 1979.
18
C ROYALTIES HAVE BEEN PAID TO AERE-UK FOR USE OF THEIR CODES
19
C IN THE PACKAGE GIVEN HERE. ANY PRIMARY USAGE OF THE HARWELL
20
C SUBROUTINES REQUIRES A ROYALTY AGREEMENT AND PAYMENT BETWEEN
21
C THE USER AND AERE-UK. ANY USAGE OF THE SANDIA WRITTEN CODES
22
C SPLP( ) (WHICH USES THE HARWELL SUBROUTINES) IS PERMITTED.
24
C IP(I,1),IP(I,2) POINT TO THE START OF ROW/COL I.
25
C IW(I,1),IW(I,2) HOLD THE NUMBER OF NON-ZEROS IN ROW/COL I.
26
C DURING THE MAIN BODY OF THIS SUBROUTINE THE VECTORS IW(.,3),IW(.,5),
27
C IW(.,7) ARE USED TO HOLD DOUBLY LINKED LISTS OF ROWS THAT HAVE
28
C NOT BEEN PIVOTAL AND HAVE EQUAL NUMBERS OF NON-ZEROS.
29
C IW(.,4),IW(.,6),IW(.,8) HOLD SIMILAR LISTS FOR THE COLUMNS.
30
C IW(I,3),IW(I,4) HOLD FIRST ROW/COLUMN TO HAVE I NON-ZEROS
31
C OR ZERO IF THERE ARE NONE.
32
C IW(I,5), IW(I,6) HOLD ROW/COL NUMBER OF ROW/COL PRIOR TO ROW/COL I
33
C IN ITS LIST, OR ZERO IF NONE.
34
C IW(I,7), IW(I,8) HOLD ROW/COL NUMBER OF ROW/COL AFTER ROW/COL I
35
C IN ITS LIST, OR ZERO IF NONE.
36
C FOR ROWS/COLS THAT HAVE BEEN PIVOTAL IW(I,5),IW(I,6) HOLD NEGATION OF
37
C POSITION OF ROW/COL I IN THE PIVOTAL ORDERING.
40
C***ROUTINES CALLED LA05ES, MC20AS, R1MACH, XERMSG, XSETUN
41
C***COMMON BLOCKS LA05DS
42
C***REVISION HISTORY (YYMMDD)
44
C 890531 Changed all specific intrinsics to generic. (WRB)
45
C 890605 Corrected references to XERRWV. (WRB)
46
C 890831 Modified array declarations. (WRB)
47
C 891214 Prologue converted to Version 4.0 format. (BAB)
48
C 900315 CALLs to XERROR changed to CALLs to XERMSG. (THJ)
49
C 900402 Added TYPE section. (WRB)
50
C 900510 Convert XERRWV calls to XERMSG calls. (RWC)
51
C***END PROLOGUE LA05AS
53
INTEGER IND(IA,2), IW(N,8)
54
REAL A(*), AMAX, AU, AM, G, U, SMALL, W(*)
56
CHARACTER*8 XERN0, XERN1, XERN2
58
COMMON /LA05DS/ SMALL, LP, LENL, LENU, NCP, LROW, LCOL
59
C EPS IS THE RELATIVE ACCURACY OF FLOATING-POINT COMPUTATION
62
C***FIRST EXECUTABLE STATEMENT LA05AS
64
EPS = 2.0E0 * R1MACH(4)
68
C SET THE OUTPUT UNIT NUMBER FOR THE ERROR PROCESSOR.
69
C THE USAGE OF THIS ERROR PROCESSOR IS DOCUMENTED IN THE
70
C SANDIA LABS. TECH. REPT. SAND78-1189, BY R E JONES.
72
IF (U.GT.1.0E0) U = 1.0E0
83
C FLUSH OUT SMALL ENTRIES, COUNT ELEMENTS IN ROWS AND COLUMNS
87
IF (L.GT.LENU) GO TO 90
89
IF (ABS(A(K)).LE.SMALL) GO TO 70
93
IF (I.LT.1 .OR. I.GT.N) GO TO 680
94
IF (J.LT.1 .OR. J.GT.N) GO TO 680
101
IND(L,1) = IND(LENU,1)
102
IND(L,2) = IND(LENU,2)
109
C MCP IS THE MAXIMUM NUMBER OF COMPRESSES PERMITTED BEFORE AN
110
C ERROR RETURN RESULTS.
113
C CHECK FOR NULL ROW OR COLUMN AND INITIALIZE IP(I,2) TO POINT
114
C JUST BEYOND WHERE THE LAST COMPONENT OF COLUMN I OF A WILL
121
IF (IW(IR,L).LE.0) GO TO 700
125
C CHECK FOR DOUBLE ENTRIES WHILE USING THE NEWLY CONSTRUCTED
126
C ROW FILE TO CONSTRUCT THE COLUMN FILE. NOTE THAT BY PUTTING
127
C THE ENTRIES IN BACKWARDS AND DECREASING IP(J,2) EACH TIME IT
128
C IS USED WE AUTOMATICALLY LEAVE IT POINTING TO THE FIRST ELEMENT.
129
CALL MC20AS(N, LENU, A, IND(1,2), IP, IND(1,1), 0)
136
IF (IW(J,5).EQ.IR) GO TO 660
145
C SET UP LINKED LISTS OF ROWS AND COLS WITH EQUAL NUMBERS OF NON-ZEROS.
153
IF (IN.NE.0) IW(IN,L+4) = I
158
C START OF MAIN ELIMINATION LOOP.
160
C FIND PIVOT. JCOST IS MARKOWITZ COST OF CHEAPEST PIVOT FOUND SO FAR,
161
C WHICH IS IN ROW IPP AND COLUMN JP.
163
C LOOP ON LENGTH OF COLUMN TO BE SEARCHED
165
IF (JCOST.LE.(NZ-1)**2) GO TO 250
167
C SEARCH COLUMNS WITH NZ NON-ZEROS.
169
IF (J.LE.0) GO TO 200
171
KL = KP + IW(J,2) - 1
174
KCOST = (NZ-1)*(IW(I,1)-1)
175
IF (KCOST.GE.JCOST) GO TO 180
176
IF (NZ.EQ.1) GO TO 170
177
C FIND LARGEST ELEMENT IN ROW OF POTENTIAL PIVOT.
180
K2 = IW(I,1) + K1 - 1
182
AMAX = MAX(AMAX,ABS(A(KK)))
183
IF (IND(KK,2).EQ.J) KJ = KK
185
C PERFORM STABILITY TEST.
186
IF (ABS(A(KJ)).LT.AMAX*U) GO TO 180
190
IF (JCOST.LE.(NZ-1)**2) GO TO 250
194
C SEARCH ROWS WITH NZ NON-ZEROS.
197
IF (I.LE.0) GO TO 240
200
KL = KP + IW(I,1) - 1
201
C FIND LARGEST ELEMENT IN THE ROW
203
AMAX = MAX(ABS(A(K)),AMAX)
207
C PERFORM STABILITY TEST.
208
IF (ABS(A(K)).LT.AU) GO TO 220
210
KCOST = (NZ-1)*(IW(J,2)-1)
211
IF (KCOST.GE.JCOST) GO TO 220
215
IF (JCOST.LE.(NZ-1)**2) GO TO 250
222
C REMOVE ROWS AND COLUMNS INVOLVED IN ELIMINATION FROM ORDERING VECTORS.
224
KL = IW(JP,2) + KP - 1
230
IF (IL.EQ.0) GO TO 260
235
270 IF (IN.GT.0) IW(IN,L+4) = IL
238
KL = KP + IW(IPP,1) - 1
243
C ELIMINATE PIVOTAL ROW FROM COLUMN FILE AND FIND PIVOT IN ROW FILE.
247
IW(J,2) = IW(J,2) - 1
250
IF (IPP.EQ.IND(KC,1)) GO TO 310
252
310 IND(KC,1) = IND(KLC,1)
256
C BRING PIVOT TO FRONT OF PIVOTAL ROW.
260
IND(KR,2) = IND(KP,2)
263
C PERFORM ELIMINATION ITSELF, LOOPING ON NON-ZEROS IN PIVOT COLUMN.
265
IF (NZC.EQ.0) GO TO 550
267
KC = IP(JP,2) + NC - 1
269
C SEARCH NON-PIVOT ROW FOR ELEMENT TO BE ELIMINATED.
271
KRL = KR + IW(IR,1) - 1
273
IF (JP.EQ.IND(KNP,2)) GO TO 340
275
C BRING ELEMENT TO BE ELIMINATED TO FRONT OF ITS ROW.
279
IND(KNP,2) = IND(KR,2)
282
C COMPRESS ROW FILE UNLESS IT IS CERTAIN THAT THERE IS ROOM FOR NEW ROW.
283
IF (LROW+IW(IR,1)+IW(IPP,1)+LENL.LE.IA) GO TO 350
284
IF (NCP.GE.MCP .OR. LENU+IW(IR,1)+IW(IPP,1)+LENL.GT.IA) GO
286
CALL LA05ES(A, IND(1,2), IP, N, IW, IA, .TRUE.)
289
350 KRL = KR + IW(IR,1) - 1
291
KPL = KP + IW(IPP,1) - 1
292
C PLACE PIVOT ROW (EXCLUDING PIVOT ITSELF) IN W.
293
IF (KQ.GT.KPL) GO TO 370
298
370 IP(IR,1) = LROW + 1
300
C TRANSFER MODIFIED ELEMENTS.
303
IF (KR.GT.KRL) GO TO 430
308
C IF ELEMENT IS VERY SMALL REMOVE IT FROM U.
309
IF (ABS(AU).LE.SMALL) GO TO 380
316
C REMOVE ELEMENT FROM COL FILE.
321
IF (IND(KK,1).EQ.IR) GO TO 400
323
400 IND(KK,1) = IND(KL,1)
328
C SCAN PIVOT ROW FOR FILLS.
329
430 IF (KQ.GT.KPL) GO TO 520
333
IF (ABS(AU).LE.SMALL) GO TO 500
339
C CREATE FILL IN COLUMN FILE.
343
IF (NZ .EQ. 0) GO TO 460
344
C IF POSSIBLE PLACE NEW ELEMENT AT END OF PRESENT ENTRY.
345
IF (KL.NE.LCOL) GO TO 440
346
IF (LCOL+LENL.GE.IA) GO TO 460
349
440 IF (IND(KL+1,1).NE.0) GO TO 460
352
C NEW ENTRY HAS TO BE CREATED.
353
460 IF (LCOL+LENL+NZ+1.LT.IA) GO TO 470
354
C COMPRESS COLUMN FILE IF THERE IS NOT ROOM FOR NEW ENTRY.
355
IF (NCP.GE.MCP .OR. LENU+LENL+NZ+1.GE.IA) GO TO 710
356
CALL LA05ES(A, IND, IP(1,2), N, IW(1,2), IA, .FALSE.)
359
C TRANSFER OLD ENTRY INTO NEW.
360
470 IP(J,2) = LCOL + 1
361
IF (KL .LT. K) GO TO 485
364
IND(LCOL,1) = IND(KK,1)
371
490 G = MAX(G,ABS(AU))
375
520 IW(IR,1) = LROW + 1 - IP(IR,1)
378
IF (LENL+LCOL+1.LE.IA) GO TO 530
379
C COMPRESS COL FILE IF NECESSARY.
380
IF (NCP.GE.MCP) GO TO 710
381
CALL LA05ES(A, IND, IP(1,2), N, IW(1,2), IA, .FALSE.)
390
C INSERT ROWS AND COLUMNS INVOLVED IN ELIMINATION IN LINKED LISTS
391
C OF EQUAL NUMBERS OF NON-ZEROS.
393
K2 = IW(JP,2) + K1 - 1
396
IF (K2.LT.K1) GO TO 570
399
IF (L.EQ.1) IND(K,L) = 0
401
IF (NZ.LE.0) GO TO 720
406
IF (IN.NE.0) IW(IN,L+4) = IR
408
570 K1 = IP(IPP,1) + 1
409
K2 = IW(IPP,1) + K1 - 2
413
C RESET COLUMN FILE TO REFER TO U AND STORE ROW/COL NUMBERS IN
414
C PIVOTAL ORDER IN IW(.,3),IW(.,4)
424
KL = IW(I,1) + KP - 1
427
IW(J,2) = IW(J,2) + 1
439
KL = IW(I,1) + KP - 1
449
C THE FOLLOWING INSTRUCTIONS IMPLEMENT THE FAILURE EXITS.
451
660 IF (LP.GT.0) THEN
452
WRITE (XERN1, '(I8)') IR
453
WRITE (XERN2, '(I8)') J
454
CALL XERMSG ('SLATEC', 'LA05AS', 'MORE THAN ONE MATRIX ' //
455
* 'ENTRY. HERE ROW = ' // XERN1 // ' AND COL = ' // XERN2,
461
670 IF (LP.GT.0) CALL XERMSG ('SLATEC', 'LA05AS',
462
* 'THE ORDER OF THE SYSTEM, N, IS NOT POSITIVE.', -1, 1)
466
680 IF (LP.GT.0) THEN
467
WRITE (XERN0, '(I8)') K
468
WRITE (XERN1, '(I8)') I
469
WRITE (XERN2, '(I8)') J
470
CALL XERMSG ('SLATEC', 'LA05AS', 'ELEMENT K = ' // XERN0 //
471
* ' IS OUT OF BOUNDS.$$HERE ROW = ' // XERN1 //
472
* ' AND COL = ' // XERN2, -3, 1)
477
700 IF (LP.GT.0) THEN
478
WRITE (XERN1, '(I8)') L
479
CALL XERMSG ('SLATEC', 'LA05AS', 'ROW OR COLUMN HAS NO ' //
480
* 'ELEMENTS. HERE INDEX = ' // XERN1, -2, 1)
485
710 IF (LP.GT.0) CALL XERMSG ('SLATEC', 'LA05AS',
486
* 'LENGTHS OF ARRAYS A(*) AND IND(*,2) ARE TOO SMALL.', -7, 1)
494
IF (II.GT.0) IW(II,1) = I
499
IF (L.EQ.2) XERN1 = 'COLUMNS'
500
CALL XERMSG ('SLATEC', 'LA05AS', 'DEPENDANT ' // XERN1, -5, 1)
502
740 WRITE (XERN1, '(I8)') IW(I,1)
504
IF (I+1.LE.IPV) WRITE (XERN2, '(I8)') IW(I+1,1)
505
CALL XERMSG ('SLATEC', 'LA05AS',
506
* 'DEPENDENT VECTOR INDICES ARE ' // XERN1 // ' AND ' //
509
IF (I.LE.IPV) GO TO 740