gpskca
C GPSKCA SOURCE CB215821 22/11/16 21:15:02 11500
C GPSKC SOURCE PV 18/06/18 21:15:05 9860
C ALGORITHM 582, COLLECTED ALGORITHMS FROM ACM.
C ALGORITHM APPEARED IN ACM-TRANS. MATH. SOFTWARE, VOL.8, NO. 2,
C JUN., 1982, P. 190.
C ==============================================================
C
C GIBBS-POOLE-STOCKMEYER AND GIBBS-KING ALGORITHMS ...
C
C 1. SUBROUTINES GPSKCA, GPSKCB, ..., GPSKCQ WHICH IMPLEMENT
C GIBBS-POOLE-STOCKMEYER AND GIBBS-KING ALGORITHMS ...
C
C 2. SAMPLE DRIVER PROGRAM
C
C 3. SAMPLE TEST PROBLEMS
C
C 4. OUTPUT PRODUCED BY SAMPLE DRIVER ON SAMPLE TEST PROBLEMS
C
C ALL OF THE ABOVE ARE IN 80 COLUMN FORMAT. THE FIRST TWO
C SECTIONS HAVE SEQUENCE NUMBERS IN COLUMNS 73 TO 80. THE
C THIRD SECTION HAS DATA IN ALL 80 COLUMNS. THE LAST SECTION
C HAS CARRIAGE CONTROL CHARACTERS IN COLUMN 1 AND DATA IN ALL
C 80 COLUMNS.
C
C THESE FOUR SECTIONS OF THE FILE ARE SEPARATED BY SINGLE CARDS
C OF THE FORM 'C === SEPARATOR ===' IN COLUMNS 1 TO 19
C
C ==============================================================
C
C THE SAMPLE TEST PROBLEMS INCLUDED WITH THIS CODE PROVIDE A
C MINIMAL CHECKOUT OF THE FUNCTIONING OF THE CODE. THE TEST
C PROBLEMS HAVE NUMERICAL VALUES WITH THE INTEGER PART BEING
C THE ROW INDEX, THE FRACTIONAL PART THE COLUMN INDEX, OF THE
C MATRIX AFTER GPS(K) REORDERING. THE TEST OUTPUT INCLUDES A
C LISTING OF THE REORDERED MATRIX, IN WHICH THE NUMERIC VALUES
C SHOULD APPEAR IN CORRECT POSITIONS, INTERMINGLED WITH ZEROES
C WHICH REPRESENT FILL IN THE SPARSE MATRIX FACTORIZATION.
C
C ==============================================================
C
C === SEPARATOR === BEGINNING OF GPS AND GK ALGORITHMS
C
C ==================================================================
C ==================================================================
C = =
C = B A N D W I D T H OR P R O F I L E R E D U C T I O N =
C = FOR A SPARSE AND (STRUCTURALLY) SYMMETRIC MATRIX, =
C = USING EITHER =
C = =
C = THE GIBBS-POOLE-STOCKMEYER ALGORITHM (BANDWIDTH REDUCTION) =
C = OR =
C = THE GIBBS-KING ALGORITHM (PROFILE REDUCTION) =
C = =
C ==================================================================
C ==================================================================
C = THIS CODE SUPERSEDES TOMS ALGORITHMS 508 AND 509 IN THE =
C = COLLECTED ALGORITHMS OF THE ACM (CALGO). =
C ==================================================================
C ==================================================================
C
C -------------------
C P A R A M E T E R S
C -------------------
C
IMPLICIT INTEGER(I-N)
INTEGER N, RSTART(N), WRKLEN, BANDWD, PROFIL, ERROR, SPACE
C
CIBM INTEGER *2 DEGREE(N), CONNEC(1), PERMUT(N), WORK(WRKLEN)
C
LOGICAL OPTPRO
C
C ------------------------------------------------------------------
C
C INPUT PARAMETERS:
C ----- ----------
C
C N -- THE DIMENSION OF THE MATRIX
C
C DEGREE,
C RSTART,
C CONNEC -- DESCRIBE THE STRUCTURE OF THE SPARSE MATRIX.
C DEGREE(I) SPECIFIES THE NUMBER OF NON-ZERO
C OFF-DIAGONAL ENTRIES IN THE I-TH ROW OF THE
C SPARSE MATRIX. THE COLUMN INDICES OF THESE
C ENTRIES ARE GIVEN IN CONSECUTIVE LOCATIONS IN
C CONNEC, STARTING AT LOCATION RSTART(I).
C IN OTHER WORDS, THE INDICES OF THE NON-ZERO
C OFF-DIAGONAL ELEMENTS OF THE I-TH ROW ARE FOUND
C IN:
C CONNEC (RSTART(I)),
C CONNEC (RSTART(I) + 1),
C . . .
C CONNEC (RSTART(I) + DEGREE(I) - 1)
C
C DIMENSIONS:
C RSTART IS DIMENSION N (OR LONGER).
C DEGREE IS DIMENSION N (OR LONGER).
C CONNEC IS DIMENSION ROUGHLY THE NUMBER OF NON-
C ZERO ENTRIES IN THE MATRIX.
C
C OPTPRO -- .TRUE. IF REDUCING THE PROFILE OF THE MATRIX
C IS MORE IMPORTANT THAN REDUCING THE
C BANDWIDTH
C .FALSE. IF BANDWIDTH REDUCTION IS MOST IMPORTANT
C
C WRKLEN -- THE ACTUAL LENGTH OF THE VECTOR WORK AS SUPPLIED
C BY THE USER. SEE THE DISCUSSION OF THE WORKSPACE
C 'WORK' BELOW FOR TYPICAL STORAGE REQUIREMENTS.
C THE VALUE OF WRKLEN WILL BE USED TO ENSURE THAT
C THE ROUTINE WILL NOT USE MORE STORAGE THAN IS
C AVAILABLE. IF NOT ENOUGH SPACE IS GIVEN IN WORK
C TO PERMIT A SOLUTION TO BE FOUND, THE ERROR FLAG
C WILL BE SET AND FURTHER COMPUTATION STOPPED.
C
C
C INPUT AND OUTPUT PARAMETER:
C ----- --- ------ ---------
C
C PERMUT -- ON INPUT, AN ALTERNATIVE REORDERING FOR THE
C ROWS AND COLUMNS OF THE MATRIX. PERMUT(I) GIVES
C THE POSITION IN WHICH ROW AND COLUMN I SHOULD
C BE PLACED TO REDUCE THE BANDWIDTH OR THE PROFILE.
C IF THE USER HAS NO ALTERNATIVE TO THE NATURAL
C HE SHOULD INITIALIZE PERMUT TO BE THE IDENTITY
C PERMUTATION PERMUT(I) = I .
C
C ON OUTPUT, PERMUT WILL CONTAIN THE PERMUTATION
C FOR REORDERING THE ROWS AND COLUMNS WHICH REDUCES
C THE BANDWIDTH AND/OR PROFILE. THE RESULT WILL BE
C THE REORDERING FOUND BY 'GPSKCA' OR THE REORDERING
C GIVEN BY THE USER IN 'PERMUT', WHICHEVER DOES THE
C JOB BETTER.
C
C
C OUTPUT PARAMETERS:
C ------ ----------
C
C WORK -- A TEMPORARY STORAGE VECTOR, OF LENGTH SOMEWHAT
C GREATER THAN 3N. THE SPACE BEYOND 3N REQUIRED
C IS PROBLEM-DEPENDENT. ANY PROBLEM CAN BE SOLVED
C IN 6N+3 LOCATIONS.
C MOST PROBLEMS CAN BE REORDERED WITH 4N LOCATIONS
C IN 'WORK'. IF SPACE IS NOT A CONSTRAINT, PROVIDE
C 6N+3 LOCATIONS IN 'WORK'. OTHERWISE, PROVIDE AS
C MUCH MORE THAN 3N AS IS CONVENIENT AND CHECK THE
C ERROR FLAG AND SPACE REQUIRED PARAMETERS (SEE BELOW)
C
C ON OUTPUT, THE 1ST N LOCATIONS OF WORK WILL BE
C A LISTING OF THE ORIGINAL ROW AND COLUMN INDICES AS
C THEY APPEAR IN THE COMPUTED REORDERING.
C LOCATIONS N+1, ... , 2N OF WORK WILL CONTAIN
C THE NEW POSITIONS FOR THE EQUATIONS IN THE ORDER
C FOUND BY GPSKCA. THUS, THE TWO VECTORS ARE INVERSE
C PERMUTATIONS OF EACH OTHER. IF THE ORDERING
C FOUND BY THIS ALGORITHM IS BETTER THAN THE USER-
C SUPPLIED ORDER, THE SECOND PERMUTATION VECTOR IS
C IDENTICAL TO THE RESULT RETURNED IN 'PERMUT'.
C
C BANDWD -- THE BANDWIDTH OF THE MATRIX WHEN ROWS AND COLUMNS
C ARE REORDERED IN THE ORDERING RETURNED IN PERMUT.
C
C PROFIL -- THE PROFILE OF THE MATRIX WHEN ROWS AND COLUMNS ARE
C REORDERED IN THE ORDERING RETURNED IN PERMUT.
C
C ERROR -- WILL BE EQUAL TO ZERO IF A NEW NUMBERING COULD BE
C FOUND IN THE SPACE PROVIDED. OTHERWISE, ERROR
C WILL BE SET TO A POSITIVE ERROR CODE (SEE TABLE
C GIVEN BELOW). IF THE REORDERING ALGORITHM HAS BEEN
C STOPPED BY LACK OF WORKSPACE, THE SPACE PARAMETER
C WILL BE SET TO THE NUMBER OF ADDITIONAL LOCATIONS
C REQUIRED TO COMPLETE AT LEAST THE NEXT PHASE OF
C THE ALGORITHM.
C
C WHENEVER A NON-ZERO VALUE FOR ERROR IS GIVEN
C PERMUT WILL RETAIN THE VALUES PROVIDED BY THE USER
C AND THE SCALARS BANDWD AND PROFIL WILL BE SET TO
C OUTRAGEOUS VALUES. IT IS THE USER'S RESPONSIBILITY
C TO CHECK THE STATUS OF ERROR.
C
C SPACE -- WILL INDICATE EITHER HOW MUCH SPACE THE REORDERING
C ACTUALLY REQUIRED OR HOW MUCH SPACE WILL BE
C REQUIRED TO COMPLETE THE NEXT PHASE OF THE
C REORDERING ALGORITHM. THE POSSIBLE OUTCOMES ARE ..
C
C ERROR = 0 SPACE IS THE MINIMAL VALUE FOR
C WRKLEN REQUIRED TO REORDER
C THIS MATRIX AGAIN.
C
C ERROR <> 0 SPACE IS THE MINIMUM NUMBER
C DUE TO LACK OF OF EXTRA WORKSPACE REQUIRED
C WORKSPACE TO CONTINUE THE REORDERING
C ALGORITHM ON THIS MATRIX.
C
C ERROR <> 0 SPACE = -1
C DUE TO ERROR
C IN DATA STRUCTURES
C
C
C ==================================================================
C
C ----------------------
C E R R O R C O D E S
C ----------------------
C
C ERROR CODES HAVE THE FORM 0XY OR 1XY.
C
C ERRORS OF THE FORM 1XY RESULT FROM INADEQUATE WORKSPACE.
C
C ERRORS OF THE FORM 0XY ARE INTERNAL PROGRAM CHECKS, WHICH
C MOST LIKELY OCCUR BECAUSE THE CONNECTIVITY STRUCTURE OF THE
C MATRIX IS REPRESENTED INCORRECTLY (E.G., THE DEGREE OF
C A NODE IS NOT CORRECT OR NODE I IS CONNECTED TO NODE J,
C BUT NOT CONVERSELY).
C
C THE LAST DIGIT (Y) IS MAINLY USEFUL FOR DEBUGGING THE
C THE REORDERING ALGORITHM. THE MIDDLE DIGIT (X) INDICATES
C HOW MUCH OF THE ALGORITHM HAS BEEN PERFORMED.
C THE TABLE BELOW GIVES THE CORRESPONDENCE BETWEEN THE
C VALUES OF X AND THE STRUCTURE OF THE ALGORITHM.
C X = 0 INITIAL PROCESSING
C X = 1 COMPUTING PSEUDO-DIAMETER (ALGORITHM I)
C X = 2 TRANSITION BETWEEN ALGORITHM I AND II
C X = 3 COMBINING LEVEL STRUCTURES (ALGORITHM II)
C X = 4 TRANSITION BETWEEN ALGORITHM II AND III
C X = 5 BANDWIDTH NUMBERING (ALGORITHM IIIA)
C X = 6 PROFILE NUMBERING (ALGORITHM IIIB)
C X = 7 FINAL BANDWIDTH/PROFILE COMPUTATION
C
C ==================================================================
C
C --------------------- ---------------
C A L T E R N A T I V E V E R S I O N S
C --------------------- ---------------
C
C SHORT INTEGER VERSION
C
C ON MACHINES WITH TWO OR MORE PRECISIONS FOR INTEGERS,
C ALL OF THE INPUT ARRAYS EXCEPT 'RSTART' CAN BE CONVERTED
C TO THE SHORTER PRECISION AS LONG AS THAT SHORTER PRECISION
C ALLOWS NUMBERS AS LARGE AS 'N'. A VERSION OF THIS CODE
C SUITABLE FOR USE ON IBM COMPUTERS (INTEGER * 2) IS EMBEDDED
C AS COMMENTS IN THIS CODE. ALL SUCH COMMENTS HAVE THE
C CHARACTERS 'CIBM' IN THE FIRST FOUR COLUMNS, AND PRECEDE THE
C EQUIVALENT STANDARD CODE WHICH THEY WOULD REPLACE.
C
C CONNECTIVITY COMPATIBILITY VERSION
C
C THE ORIGINAL (1976) TOMS CODE 'REDUCE' USED A LESS STORAGE
C EFFICIENT FORMAT FOR THE CONNECTIVITY TABLE 'CONNEC'.
C THE 1976 CODE USED A RECTANGULAR MATRIX OF DIMENSIONS
C N BY MAXDGR, WHERE MAXDGR IS AT LEAST AS LARGE AS
C THE MAXIMUM DEGREE OF ANY NODE IN THE GRAPH OF THE MATRIX.
C THE FORMAT USED IN THE CURRENT CODE IS OFTEN SUBSTANTIALLY
C MORE EFFICIENT. HOWEVER, FOR USERS FOR WHOM CONVERSION WILL
C BE DIFFICULT OR IMPOSSIBLE, TWO ALTERNATIVES ARE ..
C 1. SIMPLY NOTE THAT CHANGING THE ORDER OF SUBSCRIPTS
C IN A RECTANGULAR CONNECTION TABLE WILL ENABLE YOU
C TO USE THE NEW VERSION. THIS SUBROUTINE WILL ACCEPT A
C RECTANGULAR CONNECTION TABLE OF DIMENSIONS
C MAXDGR BY N,
C PROVIDED THAT RSTART(I) IS SET TO (I-1)*MAXDGR + 1.
C 2. THE AUTHOR WILL MAKE AVAILABLE A VARIANT VERSION
C 'GPSKRA', WHICH EXPECTS THE ADJACENCY MATRIX OR
C CONNECTIVITY TABLE IN THE SAME FORM AS DID 'REDUCE'.
C THIS VERSION CAN BE OBTAINED BY WRITING TO ..
C JOHN GREGG LEWIS
C BOEING COMPUTER SERVICES COMPANY
C MAIL STOP 9C-01
C P.O. BOX 24346
C SEATTLE, WA 98124
C PLEASE INCLUDE A DESCRIPTION OF THE COMPUTING
C ENVIRONMENT ON WHICH YOU WILL BE USING THE CODE.
C
C ==================================================================
C
INTEGER I, INC1, INC2, AVAIL, NXTNUM, LOWDG, STNODE, NLEFT,
1 TREE1, TREE2, DEPTH, EMPTY, STOTAL, REQD, CSPACE,
2 LVLLST, LVLPTR, ACTIVE, RVNODE, WIDTH1, WIDTH2, MXDG
C
LOGICAL REVRS1, ONEIS1
C
C ==================================================================
C
C << NUMBER ANY DEGREE ZERO NODES >>
C
C WHILE << SOME NODES YET UNNUMBERED >> DO
C << FIND A PSEUDO-DIAMETER OF THE MATRIX GRAPH >>
C << CONVERT FORM OF LEVEL TREES >>
C << COMBINE LEVEL TREES INTO ONE LEVEL STRUCTURE >>
C << CONVERT FORM OF LEVEL STRUCTURE >>
C IF OPTPRO THEN
C << RENUMBER BY KING ALGORITHM >>
C ELSE
C << RENUMBER BY REVERSE CUTHILL-MCKEE ALGORITHM >>
C
C ==================================================================
C
C ... INITIALIZE COUNTERS, THEN NUMBER ANY NODES OF DEGREE 0.
C THE LIST OF NODES, BY NEW NUMBER, WILL BE BUILT IN PLACE AT
C THE FRONT OF THE WORK AREA.
C
NXTNUM = 1
ERROR = 0
SPACE = 2*N
C
MXDG = 0
DO 300 I = 1, N
IF (DEGREE(I)) 6000, 100, 200
NXTNUM = NXTNUM + 1
GO TO 300
200 IF (DEGREE(I) .GT. MXDG) MXDG = DEGREE(I)
300 CONTINUE
C
C
C ==============================
C ... WHILE NXTNUM <= N DO ...
C ==============================
C
1000 IF ( NXTNUM .GT. N ) GO TO 2000
C
C ... FIND AN UNNUMBERED NODE OF MINIMAL DEGREE
C
LOWDG = MXDG + 1
STNODE = 0
DO 400 I = 1, N
IF ( (DEGREE(I) .LE. 0) .OR. (DEGREE(I) .GE. LOWDG) )
1 GO TO 400
LOWDG = DEGREE(I)
STNODE = I
400 CONTINUE
C
IF ( STNODE .EQ. 0 ) GO TO 6100
C
C ... SET UP POINTERS FOR THREE LISTS IN WORK AREA, THEN LOOK
C FOR PSEUDO-DIAMETER, BEGINNING WITH STNODE.
C
AVAIL = (WRKLEN - NXTNUM + 1) / 3
NLEFT = N - NXTNUM + 1
SPACE = MAX0 (SPACE, NXTNUM + 3*N - 1)
IF ( AVAIL .LT. N ) GO TO 5200
C
2 ACTIVE, DEPTH, WIDTH1, WIDTH2,
3 ERROR, SPACE)
IF ( ERROR .NE. 0 ) GO TO 5000
C
C ... DYNAMIC SPACE CHECK FOR MOST OF REMAINDER OF ALGORITHM
C
REQD = MAX0 (NXTNUM + 2*N + 3*DEPTH - 1, 3*N + 2*DEPTH + 1)
SPACE = MAX0 (SPACE, REQD)
IF ( WRKLEN .LT. REQD ) GO TO 5300
C
C
C ... OUTPUT FROM GPSKCB IS A PAIR OF LEVEL TREES, IN THE FORM
C OF LISTS OF NODES BY LEVEL. CONVERT THIS TO TWO LISTS OF
C OF LEVEL NUMBER BY NODE. AT THE SAME TIME PACK
C STORAGE SO THAT ONE OF THE LEVEL TREE VECTORS IS AT THE
C BACK END OF THE WORK AREA.
C
LVLPTR = NXTNUM + AVAIL - DEPTH
2 TREE2, WIDTH1, WIDTH2, ONEIS1, ERROR, SPACE)
IF ( ERROR .NE. 0 ) GO TO 5000
IF (( TREE1 .NE. WRKLEN - N + 1 ) .OR. (TREE2 .NE. NXTNUM))
1 GO TO 6200
C
C ... COMBINE THE TWO LEVEL TREES INTO A MORE GENERAL
C LEVEL STRUCTURE.
C
AVAIL = WRKLEN - NXTNUM + 1 - 2*N - 3*DEPTH
STOTAL = N + NXTNUM
EMPTY = STOTAL + DEPTH
INC1 = TREE1 - DEPTH
INC2 = INC1 - DEPTH
C
C
IF ( ERROR .NE. 0 ) GO TO 5000
SPACE = MAX0 (SPACE, NXTNUM + CSPACE - 1)
C
C ... COMBINED LEVEL STRUCTURE IS REPRESENTED BY GPSKCG AS
C A VECTOR OF LEVEL NUMBERS. FOR RENUMBERING PHASE,
C CONVERT THIS ALSO TO THE INVERSE PERMUTATION.
C
LVLPTR = TREE1 - (DEPTH + 1)
IF ( STOTAL + DEPTH .GT. LVLPTR ) GO TO 6300
C
IF (ERROR .NE. 0) GO TO 5000
C
C ... NOW RENUMBER ALL MEMBERS OF THIS COMPONENT USING
C EITHER A REVERSE CUTHILL-MCKEE OR A KING STRATEGY,
C AS PROFILE OR BANDWIDTH REDUCTION IS MORE IMPORTANT.
C
IF ( OPTPRO ) GO TO 500
3 ERROR, SPACE)
IF ( ERROR .NE. 0 ) GO TO 5000
GO TO 600
C
IF ( ERROR .NE. 0 ) GO TO 5000
C
C =========================================================
C ... END OF WHILE LOOP ... REPEAT IF GRAPH IS DISCONNECTED
C =========================================================
C
600 GO TO 1000
C
C ... CHECK WHETHER INITIAL NUMBERING OR FINAL NUMBERING
C PROVIDES BETTER RESULTS
C
2000 IF (WRKLEN .LT. 2*N) GO TO 5400
C
IF (OPTPRO) GO TO 2100
1 PERMUT, BANDWD, PROFIL, ERROR, SPACE)
GO TO 2200
C
1 PERMUT, BANDWD, PROFIL, ERROR, SPACE)
C
2200 RETURN
C
C
C . . . E R R O R D I A G N O S T I C S
C ---------------------------------
C
C ... ERROR DETECTED BY LOWER LEVEL ROUTINE. MAKE SURE THAT SIGNS
C OF DEGREE ARE PROPERLY SET
C
5000 DO 5100 I = 1, N
IF (DEGREE(I) .LT. 0) DEGREE(I) = -DEGREE(I)
5100 CONTINUE
C
BANDWD = -1
PROFIL = -1
RETURN
C
C ... STORAGE ALLOCATION ERRORS DETECTED IN THIS ROUTINE
C
5200 ERROR = 101
SPACE = -1
GO TO 5000
C
5300 ERROR = 102
SPACE = -1
GO TO 5000
C
5400 ERROR = 10
SPACE = 2*N - WRKLEN
GO TO 5000
C
C ... DATA STRUCTURE ERRORS DETECTED IN THIS ROUTINE
C
6000 ERROR = 1
GO TO 6900
C
6100 ERROR = 2
GO TO 6900
C
6200 ERROR = 3
GO TO 6900
C
6300 ERROR = 4
C
6900 SPACE = -1
GO TO 5000
END
1 STNODE, RVNODE, WORK, FORWD, BESTBK, NNODES,
2 DEPTH, FWIDTH, BWIDTH, ERROR, SPACE)
C
C ==================================================================
C
C FIND A PSEUDO-DIAMETER OF THE MATRIX GRAPH ...
C
C << BUILD A LEVEL TREE FROM STNODE >>
C REPEAT
C << BUILD A LEVEL TREE FROM EACH NODE 'BKNODE' IN THE
C DEEPEST LEVEL OF STNODE'S TREE >>
C << REPLACE 'STNODE' WITH 'BKNODE' IF A DEEPER AND
C NARROWER TREE WAS FOUND. >>
C UNTIL
C << NO FURTHER IMPROVEMENT MADE >>
C
C ... HEURISTIC ABOVE DIFFERS FROM THE ALGORITHM PUBLISHED IN
C SIAM J. NUMERICAL ANALYSIS, BUT MATCHES THE CODE
C DISTRIBUTED BY TOMS.
C
C
C PARAMETERS :
C
C N, DEGREE, RSTART & CONNEC DESCRIBE THE MATRIX STRUCTURE
C
C WORK -- WORKING SPACE, OF LENGTH 3*AVAIL, USED TO STORE
C THREE LEVEL TREES.
C
C STNODE IS INITIALLY THE NUMBER OF A NODE TO BE USED TO
C START THE PROCESS, TO BE THE ROOT OF THE FIRST TREE.
C ON OUTPUT, STNODE IS THE END OF THE PSEUDO-DIAMETER WHOSE
C LEVEL TREE IS NARROWEST.
C
C RVNODE WILL BE THE OTHER END OF THE PSEUDO-DIAMETER.
C
C NNODES WILL BE THE NUMBER OF NODES IN THIS CONNECTED
C COMPONNENT OF THE MATRIX GRAPH, I.E., THE LENGTH OF
C THE LEVEL TREES.
C
C DEPTH -- THE DEPTH OF THE LEVEL TREES BEING RETURNED,
C I.E., THE LENGTH OF THE PSEUDO-DIAMETER.
C
C ==================================================================
C
C STRUCTURE OF WORKSPACE ...
C
C ---------------------------------------------------------------
C : NUMBERED : TLIST1 PTR1 : TLIST2 PTR2 : TLIST3 PTR3 :
C ---------------------------------------------------------------
C
C TLISTI IS A LIST OF NODES OF LENGTH 'ACTIVE'
C PTRI IS A LIST OF POINTERS INTO TLISTI, OF LENGTH 'DEPTH+1'
C
C ==================================================================
C
IMPLICIT INTEGER(I-N)
INTEGER N, RSTART(N), AVAIL, NLEFT,
1 STNODE, RVNODE, FORWD, BESTBK, NNODES, DEPTH, FWIDTH,
4 BWIDTH, ERROR, SPACE
C
CIBM INTEGER *2 DEGREE(N), CONNEC(1), WORK(AVAIL,3)
C
C ----------------
C
INTEGER BACKWD, MXDPTH, WIDTH, FDEPTH, LSTLVL,
1 NLAST, T, I, BKNODE, LSTLVI
C
LOGICAL IMPROV
C
C
C ... BUILD INITIAL LEVEL TREE FROM 'STNODE'. FIND OUT HOW MANY
C NODES LIE IN THE CURRENT CONNECTED COMPONENT.
C
FORWD = 1
BACKWD = 2
BESTBK = 3
C
2 SPACE)
IF ( ERROR .NE. 0 ) GO TO 5000
C
MXDPTH = AVAIL - NNODES - 1
C
C ==========================================
C REPEAT UNTIL NO DEEPER TREES ARE FOUND ...
C ==========================================
C
1000 FWIDTH = WIDTH
FDEPTH = DEPTH
LSTLVL = AVAIL - DEPTH + 1
BWIDTH = N+1
C
C ... SORT THE DEEPEST LEVEL OF 'FORWD' TREE INTO INCREASING
C ORDER OF NODE DEGREE.
C
IF (ERROR .NE. 0) GO TO 6000
C
C ... BUILD LEVEL TREE FROM NODES IN 'LSTLVL' UNTIL A DEEPER
C AND NARROWER TREE IS FOUND OR THE LIST IS EXHAUSTED.
C
IMPROV = .FALSE.
DO 1200 I = 1, NLAST
LSTLVI = LSTLVL + I - 1
2 BWIDTH, ERROR, SPACE)
IF ( ERROR .NE. 0 ) GO TO 5000
C
IF ( DEPTH .LE. FDEPTH ) GO TO 1100
C
C ... NEW DEEPER TREE ... MAKE IT NEW 'FORWD' TREE
C AND BREAK OUT OF 'DO' LOOP.
C
IMPROV = .TRUE.
T = FORWD
FORWD = BACKWD
BACKWD = T
STNODE = BKNODE
GO TO 1300
C
C ... ELSE CHECK FOR NARROWER TREE.
C
1100 IF ( WIDTH .GE. BWIDTH ) GO TO 1200
T = BESTBK
BESTBK = BACKWD
BACKWD = T
BWIDTH = WIDTH
RVNODE = BKNODE
1200 CONTINUE
C
C ... END OF REPEAT LOOP
C ----------------------
C
1300 IF ( IMPROV ) GO TO 1000
C
DEPTH = FDEPTH
RETURN
C
C ... IN CASE OF ERROR, SIMPLY RETURN ERROR FLAG TO USER.
C
5000 RETURN
C
6000 ERROR = 11
SPACE = -1
RETURN
C
END
2 SPACE)
C
C ==================================================================
C BUILD THE LEVEL TREE ROOTED AT 'STNODE' IN THE SPACE PROVIDED IN
C LIST. CHECK FOR OVERRUN OF SPACE ALLOCATION.
C ==================================================================
C
IMPLICIT INTEGER(I-N)
INTEGER N, RSTART(N), STNODE, AVAIL, NLEFT,
C
CIBM INTEGER *2 DEGREE(N), CONNEC(1), LIST(AVAIL)
C
C ... PARAMETERS:
C
C INPUT ...
C
C N, DEGREE, RSTART, CONNEC -- DESCRIBE THE MATRIX STRUCTURE
C
C STNODE -- THE ROOT OF THE LEVEL TREE.
C
C AVAIL -- THE LENGTH OF THE WORKING SPACE AVAILABLE
C
C NLEFT -- THE NUMBER OF NODES YET TO BE NUMBERED
C
C LIST -- THE WORKING SPACE.
C
C OUTPUT ...
C
C ACTIVE -- THE NUMBER OF NODES IN THE COMPONENT
C
C DEPTH -- THE DEPTH OF THE LEVEL TREE ROOTED AT STNODE.
C
C WIDTH -- THE WIDTH OF THE LEVEL TREE ROOTED AT STNODE.
C
C ERROR -- ZERO UNLESS STORAGE WAS INSUFFICIENT.
C
C ------------------------------------------------------------------
C
INTEGER LSTART, NLEVEL, FRONT, J, NEWNOD, PTR, CDGREE,
1 LFRONT, LISTJ
C
C ... BUILD THE LEVEL TREE USING LIST AS A QUEUE AND LEAVING
C THE NODES IN PLACE. THIS GENERATES THE NODES ORDERED BY LEVEL
C PUT POINTERS TO THE BEGINNING OF EACH LEVEL, BUILDING FROM
C THE BACK OF THE WORK AREA.
C
DEPTH = 0
WIDTH = 0
ERROR = 0
LSTART = 1
FRONT = 1
DEGREE (STNODE) = -DEGREE (STNODE)
LIST (AVAIL) = 1
NLEVEL = AVAIL
C
C ... REPEAT UNTIL QUEUE BECOMES EMPTY OR WE RUN OUT OF SPACE.
C ------------------------------------------------------------
C
1000 IF ( FRONT .LT. LSTART ) GO TO 1100
C
C ... FIRST NODE OF LEVEL. UPDATE POINTERS.
C
WIDTH = MAX0 (WIDTH, LSTART - LIST(NLEVEL))
NLEVEL = NLEVEL - 1
DEPTH = DEPTH + 1
LIST (NLEVEL) = LSTART
C
C ... FIND ALL NEIGHBORS OF CURRENT NODE, ADD THEM TO QUEUE.
C
1100 LFRONT = LIST (FRONT)
PTR = RSTART (LFRONT)
CDGREE = -DEGREE (LFRONT)
IF (CDGREE .LE. 0) GO TO 6000
DO 1200 J = 1, CDGREE
PTR = PTR + 1
C
C ... ADD TO QUEUE ONLY NODES NOT ALREADY IN QUEUE
C
IF ( DEGREE(NEWNOD) .LE. 0 ) GO TO 1200
DEGREE (NEWNOD) = -DEGREE (NEWNOD)
1200 CONTINUE
FRONT = FRONT + 1
C
C ... IS QUEUE EMPTY?
C -------------------
C
C
C ... YES, THE TREE IS BUILT. UNDO OUR MARKINGS.
C
LISTJ = LIST(J)
DEGREE (LISTJ) = -DEGREE (LISTJ)
1300 CONTINUE
C
RETURN
C
C ... INSUFFICIENT STORAGE ...
C
ERROR = 110
RETURN
C
6000 ERROR = 12
SPACE = -1
RETURN
C
END
1 ACTIVE, MXDPTH, LIST, DEPTH, WIDTH, MAXWID,
2 ERROR, SPACE)
C
C ==================================================================
C BUILD THE LEVEL TREE ROOTED AT 'STNODE' IN THE SPACE PROVIDED IN
C LIST. OVERFLOW CHECK NEEDED ONLY ON DEPTH OF TREE.
C
C BUILD THE LEVEL TREE TO COMPLETION ONLY IF THE WIDTH OF ALL
C LEVELS IS SMALLER THAN 'MAXWID'. IF A WIDER LEVEL IS FOUND
C TERMINATE THE CONSTRUCTION.
C ==================================================================
C
IMPLICIT INTEGER(I-N)
1 DEPTH, WIDTH, MAXWID, ERROR, SPACE
C
CIBM INTEGER *2 DEGREE(N), CONNEC(1), LIST(AVAIL)
C
C ... PARAMETERS:
C
C INPUT ...
C
C N, DEGREE, RSTART, CONNEC -- DESCRIBE THE MATRIX STRUCTURE
C
C STNODE -- THE ROOT OF THE LEVEL TREE.
C
C AVAIL -- THE LENGTH OF THE WORKING SPACE AVAILABLE
C
C NLEFT -- THE NUMBER OF NODES YET TO BE NUMBERED
C
C ACTIVE -- THE NUMBER OF NODES IN THE COMPONENT
C
C MXDPTH -- MAXIMUM DEPTH OF LEVEL TREE POSSIBLE IN
C ALLOTTED WORKING SPACE
C
C LIST -- THE WORKING SPACE.
C
C OUTPUT ...
C
C DEPTH -- THE DEPTH OF THE LEVEL TREE ROOTED AT STNODE.
C
C WIDTH -- THE WIDTH OF THE LEVEL TREE ROOTED AT STNODE.
C
C MAXWID -- LIMIT ON WIDTH OF THE TREE. TREE WILL NOT BE
C USED IF WIDTH OF ANY LEVEL IS AS GREAT AS
C MAXWID, SO CONSTRUCTION OF TREE NEED NOT
C CONTINUE IF ANY LEVEL THAT WIDE IS FOUND.
C ERROR -- ZERO UNLESS STORAGE WAS INSUFFICIENT.
C
C ------------------------------------------------------------------
C
INTEGER LSTART, NLEVEL, FRONT, J, NEWNOD, PTR, BACK,
1 SPTR, FPTR, LFRONT, LISTJ
C
C ... BUILD THE LEVEL TREE USING LIST AS A QUEUE AND LEAVING
C THE NODES IN PLACE. THIS GENERATES THE NODES ORDERED BY LEVEL
C PUT POINTERS TO THE BEGINNING OF EACH LEVEL, BUILDING FROM
C THE BACK OF THE WORK AREA.
C
BACK = 1
DEPTH = 0
WIDTH = 0
ERROR = 0
LSTART = 1
FRONT = 1
LIST (BACK) = STNODE
DEGREE (STNODE) = -DEGREE (STNODE)
LIST (AVAIL) = 1
NLEVEL = AVAIL
C
C ... REPEAT UNTIL QUEUE BECOMES EMPTY OR WE RUN OUT OF SPACE.
C ------------------------------------------------------------
C
1000 IF ( FRONT .LT. LSTART ) GO TO 1100
C
C ... FIRST NODE OF LEVEL. UPDATE POINTERS.
C
LSTART = BACK + 1
WIDTH = MAX0 (WIDTH, LSTART - LIST(NLEVEL))
IF ( WIDTH .GE. MAXWID ) GO TO 2000
NLEVEL = NLEVEL - 1
DEPTH = DEPTH + 1
IF ( DEPTH .GT. MXDPTH ) GO TO 5000
LIST (NLEVEL) = LSTART
C
C ... FIND ALL NEIGHBORS OF CURRENT NODE, ADD THEM TO QUEUE.
C
1100 LFRONT = LIST (FRONT)
SPTR = RSTART (LFRONT)
FPTR = SPTR - DEGREE (LFRONT) - 1
DO 1200 PTR = SPTR, FPTR
C
C ... ADD TO QUEUE ONLY NODES NOT ALREADY IN QUEUE
C
IF ( DEGREE(NEWNOD) .LE. 0 ) GO TO 1200
DEGREE (NEWNOD) = -DEGREE (NEWNOD)
BACK = BACK + 1
LIST (BACK) = NEWNOD
1200 CONTINUE
FRONT = FRONT + 1
C
C ... IS QUEUE EMPTY?
C -------------------
C
IF ( FRONT .LE. BACK ) GO TO 1000
C
C ... YES, THE TREE IS BUILT. UNDO OUR MARKINGS.
C
C
1300 DO 1400 J = 1, BACK
LISTJ = LIST(J)
DEGREE (LISTJ) = -DEGREE (LISTJ)
1400 CONTINUE
C
RETURN
C
C ... ABORT GENERATION OF TREE BECAUSE IT IS ALREADY TOO WIDE
C
2000 WIDTH = N + 1
DEPTH = 0
GO TO 1300
C
C ... INSUFFICIENT STORAGE ...
C
ERROR = 111
RETURN
C
6000 ERROR = 13
SPACE = -1
RETURN
C
END
1 LVLLST, LVLPTR, WORK, NXTNUM, TREE1, TREE2,
2 WIDTH1, WIDTH2, ONEIS1, ERROR, SPACE)
C
C ==================================================================
C
C TRANSITION BETWEEN ALGORITHM I AND ALGORITHM II OF
C THE GIBBS-POOLE-STOCKMEYER PAPER.
C
C IN THIS IMPLEMENTATION ALGORITHM I REPRESENTS LEVEL TREES AS
C LISTS OF NODES ORDERED BY LEVEL. ALGORITHM II APPEARS TO REQUIRE
C LEVEL NUMBERS INDEXED BY NODE -- VECTORS FOR EFFICIENCY.
C THIS SUBROUTINE CHANGES THE LEVEL TREE REPRESENTATION TO THAT
C REQUIRED BY ALGORITHM II. NOTE THAT THE FIRST ALGORITHM CAN BE
C CARRIED OUT WITH THE LEVEL NUMBER VECTOR FORMAT, PROBABLY REQURING
C MORE COMPUTATION TIME, BUT PERHAPS LESS STORAGE.
C
C INPUT: TWO LEVEL TREES, AS LEVEL LISTS AND LEVEL POINTERS,
C FOUND IN TWO OF THE THREE COLUMNS OF THE ARRAYS 'LVLLST'
C AND 'LVLPTR'
C
C OUTPUT: TWO LEVEL TREES, AS VECTORS OF LEVEL NUMBERS,
C ONE PACKED TO THE FRONT, ONE TO THE REAR OF THE WORKING
C AREA 'WORK'. NOTE THAT 'WORK', 'LVLLST' AND 'LVLPTR'
C SHARE COMMON LOCATIONS.
C
C ================================================================
C
C ... STRUCTURE OF WORKSPACE
C
C INPUT .. (OUTPUT FROM GPSKCB)
C
C --------------------------------------------------------------
C : NUMBERED : TLIST1 PTR1 : TLIST2 PTR2 : TLIST3 PTR3 :
C --------------------------------------------------------------
C
C OUTPUT .. (GOES TO COMBIN)
C
C --------------------------------------------------------------
C : NUMBERED : TREE2 : ... : TREE1 :
C --------------------------------------------------------------
C
C ==================================================================
C
IMPLICIT INTEGER(I-N)
INTEGER N, AVAIL, ACTIVE, DEPTH, WRKLEN, NXTNUM,
1 WIDTH1, WIDTH2, TREE1, TREE2, ERROR, SPACE
C
CIBM INTEGER *2 LVLLST(AVAIL,3), LVLPTR(AVAIL,3), WORK(WRKLEN)
C
LOGICAL ONEIS1
C
C ------------------------------------------------------------------
C
INTEGER I, BTREE, FTREE, FWIDTH, BWIDTH
C
C
C ... CHECK THAT WE HAVE ENOUGH ROOM TO DO THE NECESSARY UNPACKING
C
IF (3*AVAIL .GT. WRKLEN) GO TO 6000
IF (AVAIL .LT. N) GO TO 5100
C
C ... INPUT HAS THREE POSSIBLE CASES:
C LVLLST(*,1) IS EMPTY
C LVLLST(*,2) IS EMPTY
C LVLLST(*,3) IS EMPTY
C
FTREE = TREE1
BTREE = TREE2
FWIDTH = WIDTH1
BWIDTH = WIDTH2
C
TREE1 = WRKLEN - N + 1
TREE2 = NXTNUM
C
IF ( (FTREE .EQ. 1) .OR. (BTREE .EQ. 1) ) GO TO 300
C
C ... CASE 1: 1ST SLOT IS EMPTY. UNPACK 3 INTO 1, 2 INTO 3
C
IF (FTREE .NE. 2) GO TO 100
ONEIS1 = .TRUE.
WIDTH2 = BWIDTH
WIDTH1 = FWIDTH
GO TO 200
C
100 ONEIS1 = .FALSE.
WIDTH1 = BWIDTH
WIDTH2 = FWIDTH
C
C
C
GO TO 1000
C
C
300 IF ( (FTREE .EQ. 2) .OR. (BTREE .EQ. 2) ) GO TO 600
C
C ... CASE 2: 2ND SLOT IS EMPTY. TO ENABLE COMPLETE
C REPACKING, MOVE 3 INTO 2, THEN FALL INTO NEXT CASE
C
LVLLST(I,2) = LVLLST(I,3)
400 CONTINUE
C
DO 500 I = 1, DEPTH
LVLPTR(I,2) = LVLPTR(I,3)
500 CONTINUE
C
C ... CASE 3: SLOT 3 IS EMPTY. MOVE 1 INTO 3, THEN 2 INTO 1.
C
600 IF (FTREE .EQ. 1) GO TO 700
ONEIS1 = .FALSE.
WIDTH1 = BWIDTH
WIDTH2 = FWIDTH
GO TO 800
C
700 ONEIS1 = .TRUE.
WIDTH1 = FWIDTH
WIDTH2 = BWIDTH
C
C
1000 RETURN
C
C ------------------------------------------------------------------
C
5100 SPACE = 3 * (N - AVAIL)
ERROR = 120
RETURN
C
6000 ERROR = 20
SPACE = -1
RETURN
C
END
1 REVERS)
C
C ==================================================================
C
C CONVERT LEVEL STRUCTURE REPRESENTATION FROM A LIST OF NODES
C GROUPED BY LEVEL TO A VECTOR GIVING LEVEL NUMBER FOR EACH NODE.
C
C LVLLST, LVLPTR -- LIST OF LISTS
C
C LVLNUM -- OUTPUT VECTOR OF LEVEL NUMBERS
C
C REVERS -- IF .TRUE., NUMBER LEVEL STRUCTURE FROM BACK END
C INSTEAD OF FROM FRONT
C
C ==================================================================
C
IMPLICIT INTEGER(I-N)
INTEGER N, ACTIVE, DEPTH
C
CIBM INTEGER *2 LVLLST(ACTIVE), LVLPTR(DEPTH), LVLNUM(N)
LOGICAL REVERS
C
C ------------------------------------------------------------------
C
INTEGER I, LEVEL, LSTART, LEND, XLEVEL, PLSTRT, LVLLSI
C
C
C ... IF NOT ALL NODES OF GRAPH ARE ACTIVE, MASK OUT THE
C NODES WHICH ARE NOT ACTIVE
C
DO 100 I = 1, N
LVLNUM(I) = 0
100 CONTINUE
C
200 DO 400 LEVEL = 1, DEPTH
XLEVEL = LEVEL
PLSTRT = DEPTH - LEVEL + 1
IF (REVERS) XLEVEL = PLSTRT
LSTART = LVLPTR (PLSTRT)
LEND = LVLPTR (PLSTRT - 1) - 1
C
DO 300 I = LSTART, LEND
LVLLSI = LVLLST(I)
LVLNUM (LVLLSI) = XLEVEL
300 CONTINUE
400 CONTINUE
C
RETURN
END
1 WIDTH2, TREE1, TREE2, WORK, WRKLEN, DEPTH,
2 INC1, INC2, TOTAL, ONEIS1, REVRS1, ERROR,
3 SPACE)
C
C ==================================================================
C
C COMBINE THE TWO ROOTED LEVEL TREES INTO A SINGLE LEVEL STRUCTURE
C WHICH MAY HAVE SMALLER WIDTH THAN EITHER OF THE TREES. THE NEW
C STRUCTURE IS NOT NECESSARILY A ROOTED STRUCTURE.
C
C PARAMETERS:
C
C N, DEGREE, RSTART, CONNEC -- GIVE THE DIMENSION AND STRUCTURE
C OF THE SPARSE SYMMETRIC MATRIX
C
C ACTIVE -- THE NUMBER OF NODES IN THIS CONNECTED COMPONENT OF
C THE MATRIX GRAPH
C
C TREE1 -- ON INPUT, ONE OF THE INPUT LEVEL TREES. ON
C OUTPUT, THE COMBINED LEVEL STRUCTURE
C
C TREE2 -- THE SECOND INPUT LEVEL TREE
C
C WIDTH1 -- THE MAXIMUM WIDTH OF A LEVEL IN TREE1
C
C WIDTH2 -- THE MAXIMUM WIDTH OF A LEVEL IN TREE2
C
C WORK -- A WORKING AREA OF LENGTH 'WRKLEN'
C
C INC1, -- VECTORS OF LENGTH 'DEPTH'
C INC2,
C TOTAL
C
C ONEIS1 -- INDICATES WHETHER TREE1 OR TREE2 REPRESENTS THE
C FORWARD TREE OR THE BACKWARDS TREE OF PHASE 1.
C USED TO MIMIC ARBITRARY TIE-BREAKING PROCEDURE OF
C ORIGINAL GIBBS-POOLE-STOCKMEYER CODE.
C
C REVRS1 -- OUTPUT PARAMETER INDICATING WHETHER A BACKWARDS
C ORDERING WAS USED FOR THE LARGEST COMPONENT OF
C THE REDUCED GRAPH
C
C ERROR -- NON-ZERO ONLY IF FAILURE OF SPACE ALLOCATION OR
C DATA STRUCTURE ERROR FOUND
C
C SPACE -- MINIMUM SPACE REQUIRED TO RERUN OR COMPLETE PHASE.
C
C ------------------------------------------------------------------
C
IMPLICIT INTEGER(I-N)
2 ERROR, SPACE
C
CIBM INTEGER *2 DEGREE(N), CONNEC(1), TREE1(N), TREE2(N),
C
LOGICAL ONEIS1, REVRS1
C
C ==================================================================
C
C << REMOVE ALL NODES OF PSEUDO-DIAMETERS >>
C << FIND CONNECTED COMPONENTS OF REDUCED GRAPH >>
C << COMBINE LEVEL TREES, COMPONENT BY COMPONENT >>
C
C ==================================================================
C
C STRUCTURE OF WORKSPACE ...
C
C ------------------------------------------------------------------
C : NUMBERED : TREE2 : TOTAL : NODES : START : SIZE : INC1 : INC2 :
C ------------------------------------------------------------------
C
C --------
C TREE1 :
C --------
C
C NUMBERED IS THE SET OF NUMBERED NODES (PROBABLY EMPTY)
C
C TREE1 AND TREE1 ARE LEVEL TREES (LENGTH N)
C TOTAL, INC1 AND INC2 ARE VECTORS OF NODE COUNTS PER LEVEL
C (LENGTH 'DEPTH')
C NODES IS THE SET OF NODES IN THE REDUCED GRAPH (THE NODES
C NOT ON ANY SHORTEST PATH FROM ONE END OF THE
C PSEUDODIAMETER TO THE OTHER)
C START, SIZE ARE POINTERS INTO 'NODES', ONE OF EACH FOR
C EACH CONNECTED COMPONENT OF THE REDUCED GRAPH.
C THE SIZES OF NODES, START AND SIZE ARE NOT KNOWN APRIORI.
C
C ==================================================================
INTEGER I, SIZE, AVAIL, CSTOP, START, COMPON, TREE1I, PCSTRT,
1 CSTART, MXINC1, MXINC2, COMPNS, MXCOMP, OFFDIA,
2 CSIZE, PCSIZE, WORKI, TWORKI
C
C ------------------------------------------------------------------
C
C ... FIND ALL SHORTEST PATHS FROM START TO FINISH. REMOVE NODES ON
C THESE PATHS AND IN OTHER CONNECTED COMPONENTS OF FULL GRAPH
C FROM FURTHER CONSIDERATION. SIGN OF ENTRIES IN TREE1 IS USED
C AS A MASK.
C
OFFDIA = ACTIVE
C
DO 100 I = 1, DEPTH
TOTAL(I) = 0
100 CONTINUE
C
DO 200 I = 1, N
TREE1I = TREE1 (I)
IF ((TREE1(I) .NE. TREE2(I)) .OR. (TREE1(I) .EQ. 0)) GO TO 200
TOTAL (TREE1I) = TOTAL (TREE1I) + 1
TREE1(I) = - TREE1(I)
OFFDIA = OFFDIA - 1
200 CONTINUE
C
IF ( OFFDIA .EQ. 0 ) GO TO 1100
IF ( OFFDIA .LT. 0 ) GO TO 6000
C
C ... FIND CONNECTED COMPONENTS OF GRAPH INDUCED BY THE NODES NOT
C REMOVED. 'MXCOMP' IS THE LARGEST NUMBER OF COMPONENTS
C REPRESENTABLE IN THE WORKING SPACE AVAILABLE.
C
AVAIL = WRKLEN - OFFDIA
MXCOMP = AVAIL/2
START = OFFDIA + 1
SIZE = START + MXCOMP
C
IF (MXCOMP .LE. 0) GO TO 5100
C
2 SPACE)
IF ( ERROR .NE. 0 ) GO TO 5000
C
C ... RECORD SPACE ACTUALLY USED (NOT INCLUDING NUMBERED )
C
SPACE = 2*N + 3*(DEPTH) + 2*COMPNS + OFFDIA
C
C ... SORT THE COMPONENT START POINTERS INTO INCREASING ORDER
C OF SIZE OF COMPONENT
C
IF (COMPNS .GT. 1)
IF (ERROR .NE. 0) GO TO 6200
C
C ... FOR EACH COMPONENT IN TURN, CHOOSE TO USE THE ORDERING OF THE
C 'FORWARD' TREE1 OR OF THE 'BACKWARD' TREE2 TO NUMBER THE NODES
C IN THIS COMPONENT. THE NUMBERING IS CHOSEN TO MINIMIZE THE
C MAXIMUM INCREMENT TO ANY LEVEL.
C
DO 1000 COMPON = 1, COMPNS
PCSTRT = START + COMPON - 1
PCSIZE = SIZE + COMPON - 1
CSTOP = CSTART + CSIZE - 1
IF ( ( CSIZE .LT. 0 ) .OR. ( CSIZE .GT. OFFDIA ) ) GO TO 6100
C
DO 300 I = 1, DEPTH
INC1(I) = 0
INC2(I) = 0
300 CONTINUE
C
MXINC1 = 0
MXINC2 = 0
C
DO 400 I = CSTART, CSTOP
TWORKI = -TREE1 (WORKI)
INC1 (TWORKI) = INC1 (TWORKI) + 1
TWORKI = TREE2 (WORKI)
INC2 (TWORKI) = INC2 (TWORKI) + 1
400 CONTINUE
C
C ... BAROQUE TESTS BELOW DUPLICATE THE GIBBS-POOLE-STOCKMEYER-
C CRANE PROGRAM, *** NOT *** THE PUBLISHED ALGORITHM.
C
DO 500 I = 1, DEPTH
IF ((INC1(I) .EQ. 0) .AND. (INC2(I) .EQ. 0)) GO TO 500
IF (MXINC1 .LT. TOTAL(I) + INC1(I))
1 MXINC1 = TOTAL(I) + INC1(I)
IF (MXINC2 .LT. TOTAL(I) + INC2(I))
1 MXINC2 = TOTAL(I) + INC2(I)
500 CONTINUE
C
C ... USE ORDERING OF NARROWER TREE UNLESS IT INCREASES
C WIDTH MORE THAN WIDER TREE. IN CASE OF TIE, USE TREE 2!
C
IF ( (MXINC1 .GT. MXINC2) .OR.
1 ( (MXINC1 .EQ. MXINC2) .AND. ( (WIDTH1 .GT. WIDTH2) .OR.
2 ( (WIDTH1 .EQ. WIDTH2)
3 .AND. ONEIS1) ) ) )
4 GO TO 700
C
IF ( COMPON .EQ. 1 ) REVRS1 = .NOT. ONEIS1
C
DO 600 I = 1, DEPTH
TOTAL(I) = TOTAL(I) + INC1(I)
600 CONTINUE
GO TO 1000
C
700 IF ( COMPON .EQ. 1 ) REVRS1 = ONEIS1
DO 800 I = CSTART, CSTOP
TREE1 (WORKI) = - TREE2 (WORKI)
800 CONTINUE
C
DO 900 I = 1, DEPTH
TOTAL(I) = TOTAL(I) + INC2(I)
900 CONTINUE
C
1000 CONTINUE
GO TO 2000
C
C ... DEFAULT WHEN THE REDUCED GRAPH IS EMPTY
C
1100 REVRS1 = .TRUE.
SPACE = 2*N
C
2000 RETURN
C
C ------------------------------------------------------------------
C
C ERROR FOUND ...
C
5000 SPACE = -1
GO TO 2000
C
5100 SPACE = 2 - AVAIL
ERROR = 131
GO TO 2000
C
6000 ERROR = 30
GO TO 5000
C
6100 ERROR = 31
GO TO 5000
C
6200 ERROR = 32
GO TO 5000
C
END
2 SPACE)
C
C ==================================================================
C
C FIND THE CONNECTED COMPONENTS OF THE GRAPH INDUCED BY THE SET
C OF NODES WITH POSITIVE 'STATUS'. WE SHALL BUILD THE LIST OF
C CONNECTED COMPONENTS IN 'WORK', WITH A LIST OF POINTERS
C TO THE BEGINNING NODES OF COMPONENTS LOCATED IN 'START'
C
C
IMPLICIT INTEGER(I-N)
INTEGER N, RSTART(N), NREDUC, MXCOMP, COMPNS, ERROR, SPACE
C
CIBM INTEGER *2 DEGREE(N), CONNEC(1), STATUS(N), WORK(NREDUC),
1 START(MXCOMP), SIZE(MXCOMP)
C
C
C PARAMETERS ...
C
C N -- DIMENSION OF THE ORIGINAL MATRIX
C DEGREE, RSTART, CONNEC -- THE STRUCTURE OF THE ORIGINAL MATRIX
C
C STATUS -- DERIVED FROM A LEVEL TREE. POSITIVE ENTRIES INDICATE
C ACTIVE NODES. NODES WITH STATUS <= 0 ARE IGNORED.
C
C NREDUC -- THE NUMBER OF ACTIVE NODES
C
C WORK -- WORK SPACE, USED AS A QUEUE TO BUILD CONNECTED
C COMPONENTS IN PLACE.
C
C MXCOMP -- MAXIMUM NUMBER OF COMPONENTS ALLOWED BY CURRENT
C SPACE ALLOCATION. MUST NOT BE VIOLATED.
C
C START -- POINTER TO BEGINNING OF I-TH CONNECTED COMPONENT
C
C SIZE -- SIZE OF EACH COMPONENT
C
C COMPNS -- NUMBER OF COMPONENTS ACTUALLY FOUND
C
C ERROR -- SHOULD BE ZERO ON RETURN UNLESS WE HAVE TOO LITTLE
C SPACE OR WE ENCOUNTER AN ERROR IN THE DATA STRUCTURE
C
C SPACE -- MAXIMUM AMOUNT OF WORKSPACE USED / NEEDED
C
C ==================================================================
C
INTEGER I, J, FREE, JPTR, NODE, JNODE, FRONT, CDGREE, ROOT
C
C ------------------------------------------------------------------
C
C
C REPEAT
C << FIND AN UNASSIGNED NODE AND START A NEW COMPONENT >>
C REPEAT
C << ADD ALL NEW NEIGHBORS OF FRONT NODE TO QUEUE, >>
C << REMOVE FRONT NODE. >>
C UNTIL <<QUEUE EMPTY>>
C UNTIL << ALL NODES ASSIGNED >>
C
FREE = 1
COMPNS = 0
ROOT = 1
C
C ... START OF OUTER REPEAT LOOP
C
C ... FIND AN UNASSIGNED NODE
C
100 DO 200 I = ROOT, N
IF (STATUS(I) .LE. 0) GO TO 200
NODE = I
GO TO 300
200 CONTINUE
GO TO 6100
C
C ... START NEW COMPONENT
C
300 COMPNS = COMPNS + 1
ROOT = NODE + 1
IF (COMPNS .GT. MXCOMP) GO TO 5000
START (COMPNS) = FREE
STATUS (NODE) = -STATUS (NODE)
FRONT = FREE
FREE = FREE + 1
C
C ... INNER REPEAT UNTIL QUEUE BECOMES EMPTY
C
FRONT = FRONT + 1
C
JPTR = RSTART (NODE)
CDGREE = DEGREE (NODE)
DO 500 J = 1, CDGREE
JPTR = JPTR + 1
IF (STATUS(JNODE) .LT. 0) GO TO 500
IF (STATUS(JNODE) .EQ. 0) GO TO 6000
STATUS (JNODE) = -STATUS (JNODE)
FREE = FREE + 1
500 CONTINUE
C
IF (FRONT .LT. FREE) GO TO 400
C
C ... END OF INNER REPEAT. COMPUTE SIZE OF COMPONENT AND
C SEE IF THERE ARE MORE NODES TO BE ASSIGNED
C
SIZE (COMPNS) = FREE - START (COMPNS)
IF (FREE .LE. NREDUC) GO TO 100
C
IF (FREE .NE. NREDUC+1) GO TO 6200
RETURN
C
C ------------------------------------------------------------------
C
5000 SPACE = NREDUC - FREE + 1
ERROR = 130
RETURN
C
6000 ERROR = 33
SPACE = -1
RETURN
C
6100 ERROR = 34
SPACE = -1
RETURN
C
6200 ERROR = 35
SPACE = -1
RETURN
END
1 LTOTAL, ERROR, SPACE)
C
C ==================================================================
C
C TRANSITIONAL SUBROUTINE, ALGORITHM II TO IIIA OR IIIB.
C
C CONVERT LEVEL STRUCTURE GIVEN AS VECTOR OF LEVEL NUMBERS FOR NODES
C TO STRUCTURE AS LIST OF NODES BY LEVEL
C
C N, ACTIVE, DEPTH -- PROBLEM SIZES
C LSTRUC -- INPUT LEVEL STRUCTURE
C LVLLST, LVLPTR -- OUTPUT LEVEL STRUCTURE
C LTOTAL -- NUMBER OF NODES AT EACH LEVEL (PRECOMPUTED)
C
IMPLICIT INTEGER(I-N)
C
CIBM INTEGER *2 LSTRUC(N), LVLLST(ACTIVE), LVLPTR(1), LTOTAL(DEPTH)
C
C ===============================================================
C
C STRUCTURE OF WORKSPACE ..
C
C INPUT (FROM COMBIN) ..
C
C ------------------------------------------------------------------
C : NUMBERED : ..(N).. : TOTAL : ... : TREE :
C ------------------------------------------------------------------
C
C OUTPUT (TO GPSKCJ OR GPSKCK) ..
C
C ------------------------------------------------------------------
C : NUMBERED : ... : TLIST : TPTR : TREE :
C ------------------------------------------------------------------
C
C HERE, NUMBERED IS THE SET OF NODES IN NUMBERED COMPONENTS
C TOTAL IS A VECTOR OF LENGTH 'DEPTH' GIVING THE NUMBER
C OF NODES IN EACH LEVEL OF THE 'TREE'.
C TLIST, TPTR ARE LISTS OF NODES OF THE TREE, ARRANGED
C BY LEVEL. TLIST IS OF LENGTH 'ACTIVE', TPTR 'DEPTH+1'.
C
C =================================================================
C
INTEGER I, ACOUNT, START, LEVEL, PLEVEL
C
C ... ESTABLISH STARTING AND ENDING POINTERS FOR EACH LEVEL
C
START = 1
DO 100 I = 1, DEPTH
LVLPTR(I) = START
START = START + LTOTAL(I)
LTOTAL(I) = START
100 CONTINUE
LVLPTR(DEPTH+1) = START
C
ACOUNT = 0
DO 300 I = 1, N
IF (LSTRUC(I)) 200, 300, 6000
200 LEVEL = -LSTRUC(I)
LSTRUC(I) = LEVEL
PLEVEL = LVLPTR (LEVEL)
LVLLST (PLEVEL) = I
LVLPTR (LEVEL) = LVLPTR (LEVEL) + 1
ACOUNT = ACOUNT + 1
IF (LVLPTR (LEVEL) .GT. LTOTAL (LEVEL)) GO TO 6100
300 CONTINUE
C
C ... RESET STARTING POINTERS
C
LVLPTR(1) = 1
DO 400 I = 1, DEPTH
LVLPTR(I+1) = LTOTAL(I)
400 CONTINUE
C
RETURN
C
C ------------------------------------------------------------------
C
6000 ERROR = 40
GO TO 6200
C
6100 ERROR = 41
C
6200 SPACE = -1
RETURN
C
END
1 NCOMPN, INVNUM, SNODE1, SNODE2, REVRS1,
2 DEPTH, LVLLST, LVLPTR, LVLNUM, ERROR,
3 SPACE)
C
C ==================================================================
C
C NUMBER THE NODES IN A GENERALIZED LEVEL STRUCTURE ACCORDING
C TO A GENERALIZATION OF THE CUTHILL MCKEE STRATEGY.
C
C N -- DIMENSION OF ORIGINAL PROBLEM
C DEGREE, RSTART, CONNEC -- GIVE STRUCTURE OF SPARSE AND
C SYMMETRIC MATRIX
C
C NCOMPN -- NUMBER OF NODES IN THIS COMPONENT OF MATRIX GRAPH
C
C INVNUM -- WILL BECOME A LIST OF THE ORIGINAL NODES IN THE ORDER
C WHICH REDUCES THE BANDWIDTH OF THE MATRIX.
C
C NXTNUM -- THE NEXT INDEX TO BE ASSIGNED (1 FOR FIRST COMPONENT)
C
C REVRS1 -- IF .TRUE., FIRST COMPONENT OF REDUCED GRAPH WAS NUMBERED
C BACKWARDS.
C
C LVLLST -- LIST OF NODES IN LEVEL TREE ORDERED BY LEVEL.
C
C LVLPTR -- POSITION OF INITIAL NODE IN EACH LEVEL OF LVLLST.
C
C LVLNUM -- LEVEL NUMBER OF EACH NODE IN COMPONENT
C
C
IMPLICIT INTEGER(I-N)
INTEGER N, RSTART(N), NCOMPN, SNODE1, SNODE2, DEPTH,
1 ERROR, SPACE
C
CIBM INTEGER *2 DEGREE(N), CONNEC(1), INVNUM(NCOMPN),
1 LVLLST(NCOMPN), LVLPTR(DEPTH), LVLNUM(N)
C
LOGICAL REVRS1
C
C
C ==================================================================
C
C NUMBERING REQUIRES TWO QUEUES, WHICH CAN BE BUILD IN PLACE
C IN INVNUM.
C
C
C ==================================================================
C A L G O R I T H M S T R U C T U R E
C ==================================================================
C
C << SET QUEUE1 TO BE THE SET CONTAINING ONLY THE START NODE. >>
C
C FOR LEVEL = 1 TO DEPTH DO
C
C BEGIN
C LOOP
C
C REPEAT
C BEGIN
C << CNODE <- FRONT OF QUEUE1 >>
C << ADD UNNUMBERED NEIGHBORS OF CNODE TO THE BACK >>
C << OF QUEUE1 OR QUEUE2 (USE QUEUE1 IF NEIGHBOR >>
C << AT SAME LEVEL, QUEUE2 IF AT NEXT LEVEL). SORT >>
C << THE NEWLY QUEUED NODES INTO INCREASING ORDER OF >>
C << DEGREE. NUMBER CNODE, DELETE IT FROM QUEUE1. >>
C END
C UNTIL
C << QUEUE1 IS EMPTY >>
C
C EXIT IF << ALL NODES AT THIS LEVEL NUMBERED >>
C
C BEGIN
C << FIND THE UNNUMBERED NODE OF MINIMAL DEGREE AT THIS >>
C << LEVEL, RESTART QUEUE1 WITH THIS NODE. >>
C END
C
C END << LOOP LOOP >>
C
C << PROMOTE QUEUE2 TO BE INITIAL QUEUE1 FOR NEXT ITERATION >>
C << OF FOR LOOP. >>
C
C END <<FOR LOOP>>
C
C ==================================================================
C
C STRUCTURE OF WORKSPACE ..
C
C --------------------------------------------------------------
C : NUMBERED : QUEUE1 : QUEUE2 : ... : TLIST : TPTR : TREE :
C --------------------------------------------------------------
C
C ON COMPLETION, WE HAVE ONLY A NEW, LONGER NUMBERED SET.
C
C ==================================================================
INTEGER I, BQ1, BQ2, FQ1, INC, CPTR, CNODE,
1 INODE, LEVEL, NLEFT, LSTART, LWIDTH, QUEUE1,
2 QUEUE2, CDGREE, XLEVEL, STNODE, ILEVEL, SQ1, SQ2,
3 NSORT, LOWDG, BPTR, LVLLSC, LVLLSB, INVNMI
C
LOGICAL FORWRD, RLEVEL
C
C ------------------------------------------------------------------
C
C ... GIBBS-POOLE-STOCKMEYER HEURISTIC CHOICE OF ORDER
C
IF (DEGREE(SNODE1) .GT. DEGREE(SNODE2)) GO TO 10
FORWRD = REVRS1
STNODE = SNODE1
GO TO 20
C
10 FORWRD = .NOT. REVRS1
STNODE = SNODE2
C
C ... SET UP INITIAL QUEUES AT FRONT OF 'INVNUM' FOR FORWRD ORDER,
C AT BACK FOR REVERSED ORDER.
C
20 IF (FORWRD) GO TO 100
INC = -1
QUEUE1 = NCOMPN
GO TO 200
C
100 INC = +1
QUEUE1 = 1
C
200 INVNUM (QUEUE1) = STNODE
RLEVEL = (LVLNUM(STNODE) .EQ. DEPTH)
LVLNUM (STNODE) = 0
FQ1 = QUEUE1
BQ1 = QUEUE1 + INC
C
C -------------------------------
C NUMBER NODES LEVEL BY LEVEL ...
C -------------------------------
C
DO 3000 XLEVEL = 1, DEPTH
LEVEL = XLEVEL
IF (RLEVEL) LEVEL = DEPTH - XLEVEL + 1
C
LSTART = LVLPTR (LEVEL)
LWIDTH = LVLPTR (LEVEL+1) - LSTART
NLEFT = LWIDTH
QUEUE2 = QUEUE1 + INC*LWIDTH
BQ2 = QUEUE2
C
C ==============================================================
C ... 'LOOP' CONSTRUCT BEGINS AT STATEMENT 1000
C THE INNER 'REPEAT' WILL BE DONE AS MANY TIMES AS
C IS NECESSARY TO NUMBER ALL THE NODES AT THIS LEVEL.
C ==============================================================
C
1000 CONTINUE
C
C ==========================================================
C ... REPEAT ... UNTIL QUEUE1 BECOMES EMPTY
C TAKE NODE FROM FRONT OF QUEUE1, FIND EACH OF ITS
C NEIGHBORS WHICH HAVE NOT YET BEEN NUMBERED, AND
C ADD THE NEIGHBORS TO QUEUE1 OR QUEUE2 ACCORDING TO
C THEIR LEVELS.
C ==========================================================
C
1100 CNODE = INVNUM (FQ1)
FQ1 = FQ1 + INC
SQ1 = BQ1
SQ2 = BQ2
NLEFT = NLEFT - 1
C
CPTR = RSTART (CNODE)
CDGREE = DEGREE (CNODE)
DO 1300 I = 1, CDGREE
CPTR = CPTR + 1
ILEVEL = LVLNUM (INODE)
IF (ILEVEL .EQ. 0) GO TO 1300
LVLNUM (INODE) = 0
IF ( ILEVEL .EQ. LEVEL ) GO TO 1200
C
IF (IABS(LEVEL-ILEVEL) .NE. 1) GO TO 6400
INVNUM (BQ2) = INODE
BQ2 = BQ2 + INC
GO TO 1300
C
1200 INVNUM (BQ1) = INODE
BQ1 = BQ1 + INC
1300 CONTINUE
C
C ==================================================
C ... SORT THE NODES JUST ADDED TO QUEUE1 AND QUEUE2
C SEPARATELY INTO INCREASING ORDER OF DEGREE.
C ==================================================
C
IF (IABS (BQ1 - SQ1) .LE. 1) GO TO 1500
NSORT = IABS (BQ1 - SQ1)
IF (FORWRD) GO TO 1400
CALL GPSKCP (NSORT, INVNUM(BQ1+1), N, DEGREE,
1 ERROR)
IF (ERROR .NE. 0) GO TO 6600
GO TO 1500
C
1400 CALL GPSKCQ (NSORT, INVNUM(SQ1), N, DEGREE,
1 ERROR)
IF (ERROR .NE. 0) GO TO 6600
C
1500 IF (IABS (BQ2 - SQ2) .LE. 1) GO TO 1700
NSORT = IABS (BQ2 - SQ2)
IF (FORWRD) GO TO 1600
CALL GPSKCP (NSORT, INVNUM(BQ2+1), N, DEGREE,
1 ERROR)
IF (ERROR .NE. 0) GO TO 6600
GO TO 1700
C
1600 CALL GPSKCQ (NSORT, INVNUM(SQ2), N, DEGREE,
1 ERROR)
IF (ERROR .NE. 0) GO TO 6600
C
C ... END OF REPEAT LOOP
C
1700 IF (FQ1 .NE. BQ1) GO TO 1100
C
C ==============================================================
C ... QUEUE1 IS NOW EMPTY ...
C IF THERE ARE ANY UNNUMBERED NODES LEFT AT THIS LEVEL,
C FIND THE ONE OF MINIMAL DEGREE AND RETURN TO THE
C REPEAT LOOP ABOVE.
C ==============================================================
C
2000 IF ((BQ1 .EQ. QUEUE2) .AND. (NLEFT .EQ. 0)) GO TO 2900
C
IF ((NLEFT .LE. 0) .OR. (NLEFT .NE. INC * (QUEUE2 - BQ1)))
1 GO TO 6200
C
LOWDG = N + 1
BPTR = N + 1
CPTR = LSTART - 1
DO 2800 I = 1, NLEFT
2600 CPTR = CPTR + 1
LVLLSC = LVLLST (CPTR)
IF (LVLNUM (LVLLSC) .EQ. LEVEL) GO TO 2700
IF (LVLNUM (LVLLSC) .NE. 0) GO TO 6300
GO TO 2600
C
2700 IF (DEGREE(LVLLSC) .GE. LOWDG) GO TO 2800
LOWDG = DEGREE (LVLLSC)
BPTR = CPTR
C
2800 CONTINUE
C
C ... MINIMAL DEGREE UNNUMBERED NODE FOUND ...
C
IF (BPTR .GT. N) GO TO 6500
LVLLSB = LVLLST (BPTR)
INVNUM (BQ1) = LVLLSB
LVLNUM (LVLLSB) = 0
BQ1 = BQ1 + INC
GO TO 1000
C
C =============================================
C ... ADVANCE QUEUE POINTERS TO MAKE QUEUE2 THE
C NEW QUEUE1 FOR THE NEXT ITERATION.
C =============================================
C
2900 QUEUE1 = QUEUE2
FQ1 = QUEUE1
BQ1 = BQ2
IF ((BQ1 .EQ. FQ1) .AND. (XLEVEL .LT. DEPTH)) GO TO 6100
C
3000 CONTINUE
C
C ... CHANGE SIGN OF DEGREE TO MARK THESE NODES AS 'NUMBERED'
C
DO 3100 I = 1, NCOMPN
INVNMI = INVNUM(I)
DEGREE (INVNMI) = -DEGREE (INVNMI)
3100 CONTINUE
C
RETURN
C
C ------------------------------------------------------------------
C
6000 SPACE = -1
RETURN
C
6100 ERROR = 51
GO TO 6000
C
6200 ERROR = 52
GO TO 6000
C
6300 ERROR = 53
GO TO 6000
C
6400 ERROR = 54
GO TO 6000
C
6500 ERROR = 55
GO TO 6000
C
6600 ERROR = 56
GO TO 6000
C
END
1 WORK, NCOMPN, DEPTH, LVLLST, LVLPTR, LVLNUM,
2 ERROR, SPACE)
C
IMPLICIT INTEGER(I-N)
INTEGER N, RSTART(N), WRKLEN, NXTNUM, NCOMPN, DEPTH, ERROR,
1 SPACE
C
CIBM INTEGER *2 DEGREE(N), CONNEC(1), WORK(WRKLEN), LVLLST(N),
1 LVLPTR(DEPTH), LVLNUM(N)
C
C ==================================================================
C
C NUMBER NODES IN A GENERALIZED LEVEL STRUCTURE ACCORDING TO
C A GENERALIZATION OF THE KING ALGORITHM, WHICH REDUCES
C THE PROFILE OF THE SPARSE SYMMETRIC MATRIX.
C
C ---------------------
C
C CODE USES A PRIORITY QUEUE TO CHOOSE THE NEXT NODE TO BE NUMBERED
C THE PRIORITY QUEUE IS REPRESENTED BY A SIMPLE LINEAR-LINKED LIST
C TO SAVE SPACE. THIS WILL REQUIRE MORE SEARCHING THAN A FULLY
C LINKED REPRESENTATION, BUT THE DATA MANIPULATION IS SIMPLER.
C
C -------------------
C
C << ESTABLISH PRIORITY QUEUE 'ACTIVE' FOR LEVEL 1 NODES >>
C
C FOR I = 1 TO DEPTH DO
C << SET QUEUE 'QUEUED' TO BE EMPTY, LIST 'NEXT' TO BE >>
C << SET OF NODES AT NEXT LEVEL. >>
C
C FOR J = 1 TO 'NODES AT THIS LEVEL' DO
C << FIND FIRST NODE IN ACTIVE WITH MINIMAL CONNECTIONS >>
C << TO 'NEXT'. NUMBER THIS NODE AND REMOVE HIM FROM >>
C << 'ACTIVE'. FOR EACH NODE IN 'NEXT' WHICH CONNECTED >>
C << TO THIS NODE, MOVE IT TO 'QUEUED' AND REMOVE IT >>
C << FROM 'NEXT'. >>
C
C << SET NEW QUEUE 'ACTIVE' TO BE 'QUEUED' FOLLOWED BY ANY >>
C << NODES STILL IN 'NEXT'. >>
C
C ==================================================================
C
C DATA STRUCTURE ASSUMPTIONS:
C THE FIRST 'NXTNUM-1' ELEMENTS OF WORK ARE ALREADY IN USE.
C THE LEVEL STRUCTURE 'LVLLST' IS CONTIGUOUS WITH WORK, THAT IS,
C IT RESIDES IN ELEMENTS WRKLEN+1, ... OF WORK. 'LVLPTR' AND
C 'LVLNUM' ARE ALSO EMBEDDED IN WORK, BEHIND 'LVLLST'. THE
C THREE VECTORS ARE PASSED SEPARATELY TO CLARIFY THE INDEXING,
C BUT THE QUEUES DEVELOPED WILL BE ALLOWED TO OVERRUN 'LVLLST'
C AS NEEDED.
C
C ... BUILD THE FIRST 'ACTIVE' QUEUE STARTING W1 LOCATIONS FROM
C THE FRONT OF THE CURRENT WORKING AREA (W1 IS THE WIDTH OF THE
C FIRST LEVEL). BUILD THE FIRST 'QUEUED' QUEUE STARTING FROM
C THE BACK OF WORK SPACE. THE LIST 'NEXT' WILL BE REALIZED
C LVLNUM(I) > 0 <== LEVEL NUMBER OF NODE. 'NEXT' IS
C SET WITH LVLNUM(I) = LEVEL+1
C LVLNUM(I) = 0 <== I-TH NODE IS IN 'QUEUED' OR IS
C NOT IN THIS COMPONENT OF GRAPH,
C OR HAS JUST BEEN NUMBERED.
C LVLNUM(I) < 0 <== I-TH NODE IS IN 'ACTIVE' AND IS
C CONNECTED TO -LVLNUM(I) NODES IN
C 'NEXT'.
C
C ==================================================================
C
C STRUCTURE OF WORKSPACE ..
C
C --------------------------------------------------------------
C : NUMBERED : DONE : ACTIVE : ALEVEL : ... : QUEUED : LVLLST :
C --------------------------------------------------------------
C
C -------------------
C LVLPTR : LVLNUM :
C -------------------
C
C IN THE ABOVE,
C NUMBERED IS THE SET OF NODES ALREADY NUMBERED FROM
C PREVIOUS COMPONENTS AND EARLIER LEVELS OF THIS COMPONENT.
C DONE, ACTIVE, ALEVEL ARE VECTORS OF LENGTH THE WIDTH OF
C THE CURRENT LEVEL. ACTIVE IS A SET OF INDICES INTO
C ALEVEL. AS THE NODES IN ALEVEL ARE NUMBERED, THEY
C ARE PLACED INTO 'DONE'.
C QUEUED IS A QUEUE OF NODES IN THE 'NEXT' LEVEL, WHICH
C GROWS FROM THE START OF THE 'NEXT' LEVEL IN LVLLST
C FORWARDS TOWARD 'ALEVEL'. QUEUED IS OF LENGTH NO MORE
C THAN THE WIDTH OF THE NEXT LEVEL.
C LVLLST IS THE LIST OF UNNUMBERED NODES IN THE TREE,
C ARRANGED BY LEVEL.
C
C ==================================================================
INTEGER I, J, K, PTR, JPTR, KPTR, LPTR, MPTR, PPTR, RPTR,
1 MPPTR, JNODE, KNODE, CNODE, LEVEL, LOWDG, UNUSED,
2 MXQUE, NNEXT, ASTART, MINDG, LSTART, LWIDTH, ACTIVE,
2 QUEUEB, QUEUED, QCOUNT, NCONNC, NACTIV, CDGREE,
3 LDGREE, NFINAL, JDGREE, STRTIC, ADDED, TWRKLN,
4 LVLLSL, CONNEJ, CONNER, ASTPTR, ACTPTR, ACTIVI,
5 ASTRTI, QUEUEI, ACPPTR
C
C ------------------------------------------------------------------
C
TWRKLN = WRKLEN + NCOMPN + N + DEPTH + 1
UNUSED = TWRKLN
C
ASTART = LVLPTR(1)
LWIDTH = LVLPTR(2) - ASTART
ASTART = WRKLEN + 1
NACTIV = LWIDTH
NFINAL = NXTNUM + NCOMPN
C
NNEXT = LVLPTR(3) - LVLPTR(2)
QUEUED = WRKLEN
QUEUEB = QUEUED
C
C ... BUILD FIRST PRIORITY QUEUE 'ACTIVE'
C
LOWDG = - (N + 1)
LPTR = LVLPTR(1)
DO 200 I = 1, LWIDTH
NCONNC = 0
LVLLSL= LVLLST (LPTR)
JPTR = RSTART (LVLLSL)
LDGREE = DEGREE(LVLLSL)
DO 100 J = 1, LDGREE
IF ( LVLNUM (CONNEJ) .EQ. 2 ) NCONNC = NCONNC - 1
JPTR = JPTR + 1
100 CONTINUE
C
LVLNUM (LVLLSL) = NCONNC
LOWDG = MAX0 (LOWDG, NCONNC)
LPTR = LPTR + 1
200 CONTINUE
C
C -----------------------------------
C NOW NUMBER NODES LEVEL BY LEVEL ...
C -----------------------------------
C
DO 2000 LEVEL = 1, DEPTH
C
C ... NUMBER ALL NODES IN THIS LEVEL
C
DO 1100 I = 1, LWIDTH
PPTR = -1
IF (NNEXT .EQ. 0) GO TO 1000
C
C ... IF NODES REMAIN IN NEXT, FIND THE EARLIEST NODE
C IN ACTIVE OF MINIMAL DEGREE.
C
MINDG = -(N+1)
DO 400 J = 1, NACTIV
ASTPTR = ASTART + PTR
IF ( LVLNUM (CNODE) .EQ. LOWDG ) GO TO 500
IF ( LVLNUM (CNODE) .LE. MINDG ) GO TO 300
MPPTR = PPTR
MPTR = PTR
MINDG = LVLNUM (CNODE)
300 PPTR = PTR
400 CONTINUE
C
C ... ESTABLISH PTR AS FIRST MIN DEGREE NODE
C PPTR AS PREDECESSOR IN LIST.
C
PTR = MPTR
PPTR = MPPTR
C
500 ASTPTR = ASTART + PTR
LOWDG = LVLNUM (CNODE)
LVLNUM (CNODE) = 0
JPTR = RSTART (CNODE)
C
C ... UPDATE CONNECTION COUNTS FOR ALL NODES WHICH
C CONNECT TO CNODE'S NEIGHBORS IN NEXT.
C
CDGREE = DEGREE(CNODE)
STRTIC = QUEUEB
C
DO 700 J = 1, CDGREE
JPTR = JPTR + 1
IF (LVLNUM (JNODE) .NE. LEVEL+1 ) GO TO 700
IF (QUEUEB .LT. MXQUE) GO TO 5000
QUEUEB = QUEUEB - 1
NNEXT = NNEXT - 1
LVLNUM (JNODE) = 0
IF (NACTIV .EQ. 1) GO TO 700
KPTR = RSTART (JNODE)
JDGREE = DEGREE (JNODE)
DO 600 K = 1, JDGREE
KPTR = KPTR + 1
IF (LVLNUM (KNODE) .GE. 0) GO TO 600
LVLNUM (KNODE) = LVLNUM (KNODE) + 1
IF (LOWDG .LT. LVLNUM(KNODE))
1 LOWDG = LVLNUM(KNODE)
600 CONTINUE
700 CONTINUE
C
C ... TO MIMIC THE ALGORITHM AS IMPLEMENTED BY GIBBS,
C SORT THE NODES JUST ADDED TO THE QUEUE INTO
C INCREASING ORDER OF ORIGINAL INDEX. (BUT, BECAUSE
C THE QUEUE IS STORED BACKWARDS IN MEMORY, THE SORT
C ROUTINE IS CALLED FOR DECREASING INDEX.)
C
C TREAT 0, 1 OR 2 NODES ADDED AS SPECIAL CASES
C
ADDED = STRTIC - QUEUEB
IF (ADDED - 2) 1000, 800, 900
C
GO TO 1000
C
IF (ERROR .NE. 0) GO TO 5500
C
C
C ... NUMBER THIS NODE AND DELETE IT FROM 'ACTIVE'.
C MARK IT UNAVAILABLE BY CHANGING SIGN OF DEGREE
C
1000 NACTIV = NACTIV - 1
ASTPTR = ASTART + PTR
DEGREE (CNODE) = -DEGREE (CNODE)
NXTNUM = NXTNUM + 1
C
C ... DELETE LINK TO THIS NODE FROM LIST
C
1100 CONTINUE
C
C ... NOW MOVE THE QUEUE 'QUEUED' FORWARD, AT THE SAME
C TIME COMPUTING CONNECTION COUNTS FOR ITS ELEMENTS.
C THEN DO THE SAME FOR THE REMAINING NODES IN 'NEXT'.
C
UNUSED = MIN0 (UNUSED, QUEUEB - MXQUE)
IF ( NXTNUM .NE. ACTIVE-1 ) GO TO 5100
IF ( LEVEL .EQ. DEPTH ) GO TO 2000
LSTART = LVLPTR (LEVEL+1)
LWIDTH = LVLPTR (LEVEL+2) - LSTART
NACTIV = LWIDTH
MXQUE = ASTART + LWIDTH
IF ( MXQUE .GT. QUEUEB + 1 ) GO TO 5000
UNUSED = MIN0 (UNUSED, QUEUEB - MXQUE + 1)
C
QCOUNT = QUEUED - QUEUEB
LOWDG = -N-1
C
PTR = LSTART
DO 1600 I = 1, LWIDTH
C
C ... CHOOSE NEXT NODE FROM EITHER 'QUEUED' OR 'NEXT'
C
IF (I .GT. QCOUNT ) GO TO 1200
QUEUEI = QUEUED + 1 - I
GO TO 1300
C
1200 CNODE = LVLLST (PTR)
PTR = PTR + 1
IF ( PTR .GT. LVLPTR(LEVEL+2) ) GO TO 5200
IF (LVLNUM (CNODE) .GT. 0) GO TO 1300
GO TO 1200
C
1300 IF ( LEVEL+1 .EQ. DEPTH ) GO TO 1500
C
RPTR = RSTART (CNODE)
NCONNC = 0
JDGREE = DEGREE (CNODE)
DO 1400 J = 1, JDGREE
IF ( LVLNUM (CONNER) .EQ. LEVEL+2 )
1 NCONNC = NCONNC - 1
RPTR = RPTR + 1
1400 CONTINUE
LVLNUM (CNODE) = NCONNC
LOWDG = MAX0 (LOWDG, NCONNC)
C
C ... ADD CNODE TO NEW 'ACTIVE' QUEUE
C
ASTRTI = ASTART + (I - 1)
1600 CONTINUE
C
IF (DEPTH .EQ. LEVEL+1 ) GO TO 1700
NNEXT = LVLPTR (LEVEL+3) - LVLPTR (LEVEL+2)
QUEUED = LSTART - 1 + LWIDTH + WRKLEN
QUEUEB = QUEUED
GO TO 2000
C
1700 NNEXT = 0
C
2000 CONTINUE
C
IF (NXTNUM .NE. NFINAL) GO TO 5300
SPACE = MAX0 (SPACE, TWRKLN - UNUSED)
RETURN
C
C
C ------------------------------------------------------------------
C
5000 SPACE = NACTIV + NNEXT
ERROR = 160
RETURN
C
5100 ERROR = 61
GO TO 5400
C
5200 ERROR = 62
GO TO 5400
C
5300 ERROR = 63
C
5400 RETURN
C
5500 ERROR = 64
GO TO 5400
C
END
1 OLDNUM, BANDWD, PROFIL, ERROR, SPACE)
C
C
IMPLICIT INTEGER(I-N)
INTEGER N, RSTART(N), BANDWD, PROFIL, ERROR, SPACE
C
CIBM INTEGER *2 DEGREE(N), CONNEC(1), INVNUM(N), NEWNUM(N), OLDNUM(N)
C
C ==================================================================
C
C
C COMPUTE THE BANDWIDTH AND PROFILE FOR THE RENUMBERING GIVEN
C BY 'INVNUM' AND ALSO FOR THE RENUMBERING GIVEN BY 'OLDNUM'.
C 'NEWNUM' WILL BE A PERMUTATION VECTOR COPY OF THE NODE
C LIST 'INVNUM'.
C
C ==================================================================
C
INTEGER I, J, JPTR, IDGREE, OLDBND, OLDPRO, NEWBND, NEWPRO,
1 OLDRWD, NEWRWD, OLDORG, NEWORG, JNODE, INVNMI
C
C ------------------------------------------------------------------
C
C ... CREATE NEWNUM AS A PERMUTATION VECTOR
C
DO 100 I = 1, N
INVNMI = INVNUM (I)
NEWNUM (INVNMI) = I
100 CONTINUE
C
C ... COMPUTE PROFILE AND BANDWIDTH FOR BOTH THE OLD AND THE NEW
C ORDERINGS.
C
OLDBND = 0
OLDPRO = 0
NEWBND = 0
NEWPRO = 0
C
DO 300 I = 1, N
IF (DEGREE(I) .EQ. 0) GO TO 300
IF (DEGREE(I) .GT. 0) GO TO 6000
IDGREE = -DEGREE(I)
DEGREE(I) = IDGREE
NEWORG = NEWNUM(I)
OLDORG = OLDNUM(I)
NEWRWD = 0
OLDRWD = 0
JPTR = RSTART (I)
C
C ... FIND NEIGHBOR WHICH IS NUMBERED FARTHEST AHEAD OF THE
C CURRENT NODE.
C
DO 200 J = 1, IDGREE
JPTR = JPTR + 1
NEWRWD = MAX0 (NEWRWD, NEWORG - NEWNUM(JNODE))
OLDRWD = MAX0 (OLDRWD, OLDORG - OLDNUM(JNODE))
200 CONTINUE
C
NEWPRO = NEWPRO + NEWRWD
NEWBND = MAX0 (NEWBND, NEWRWD)
OLDPRO = OLDPRO + OLDRWD
OLDBND = MAX0 (OLDBND, OLDRWD)
300 CONTINUE
C
C ... IF NEW ORDERING HAS BETTER BANDWIDTH THAN OLD ORDERING,
C REPLACE OLD ORDERING BY NEW ORDERING
C
IF (NEWBND .GT. OLDBND) GO TO 500
BANDWD = NEWBND
PROFIL = NEWPRO
DO 400 I = 1, N
OLDNUM(I) = NEWNUM(I)
400 CONTINUE
GO TO 600
C
C ... RETAIN OLD ORDERING
C
500 BANDWD = OLDBND
PROFIL = OLDPRO
C
600 RETURN
C
C ------------------------------------------------------------------
C
6000 SPACE = -1
ERROR = 70
RETURN
C
END
1 OLDNUM, BANDWD, PROFIL, ERROR, SPACE)
C
C
IMPLICIT INTEGER(I-N)
INTEGER N, RSTART(N), BANDWD, PROFIL, ERROR, SPACE
C
CIBM INTEGER *2 DEGREE(N), CONNEC(N), INVNUM(N), NEWNUM(N), OLDNUM(N)
C
C ==================================================================
C
C
C COMPUTE THE BANDWIDTH AND PROFILE FOR THE RENUMBERING GIVEN
C BY 'INVNUM', BY THE REVERSE OF NUMBERING 'INVNUM', AND ALSO
C BY THE RENUMBERING GIVEN IN 'OLDNUM'.
C 'NEWNUM' WILL BE A PERMUTATION VECTOR COPY OF THE NODE
C LIST 'INVNUM'.
C
C ==================================================================
C
INTEGER I, J, JPTR, IDGREE, OLDBND, OLDPRO, NEWBND, NEWPRO,
1 OLDRWD, NEWRWD, OLDORG, NEWORG, JNODE, NRVBND, NRVPRO,
2 NRVORG, NRVRWD, INVNMI, NMIP1
C
C ------------------------------------------------------------------
C
C ... CREATE NEWNUM AS A PERMUTATION VECTOR
C
DO 100 I = 1, N
INVNMI = INVNUM (I)
NEWNUM (INVNMI) = I
100 CONTINUE
C
C ... COMPUTE PROFILE AND BANDWIDTH FOR BOTH THE OLD AND THE NEW
C ORDERINGS.
C
OLDBND = 0
OLDPRO = 0
NEWBND = 0
NEWPRO = 0
NRVBND = 0
NRVPRO = 0
C
DO 300 I = 1, N
IF (DEGREE(I) .EQ. 0) GO TO 300
IF (DEGREE(I) .GT. 0) GO TO 6000
IDGREE = -DEGREE(I)
DEGREE(I) = IDGREE
NEWRWD = 0
OLDRWD = 0
NRVRWD = 0
NEWORG = NEWNUM(I)
OLDORG = OLDNUM(I)
NRVORG = N - NEWNUM(I) + 1
JPTR = RSTART (I)
C
C ... FIND NEIGHBOR WHICH IS NUMBERED FARTHEST AHEAD OF THE
C CURRENT NODE.
C
DO 200 J = 1, IDGREE
JPTR = JPTR + 1
NEWRWD = MAX0 (NEWRWD, NEWORG - NEWNUM(JNODE))
OLDRWD = MAX0 (OLDRWD, OLDORG - OLDNUM(JNODE))
NRVRWD = MAX0 (NRVRWD, NRVORG - N + NEWNUM(JNODE) - 1)
200 CONTINUE
C
NEWPRO = NEWPRO + NEWRWD
NEWBND = MAX0 (NEWBND, NEWRWD)
NRVPRO = NRVPRO + NRVRWD
NRVBND = MAX0 (NRVBND, NRVRWD)
OLDPRO = OLDPRO + OLDRWD
OLDBND = MAX0 (OLDBND, OLDRWD)
300 CONTINUE
C
C ... IF NEW ORDERING HAS BETTER BANDWIDTH THAN OLD ORDERING,
C REPLACE OLD ORDERING BY NEW ORDERING
C
IF ((NEWPRO .GT. OLDPRO) .OR. (NEWPRO .GT. NRVPRO)) GO TO 500
BANDWD = NEWBND
PROFIL = NEWPRO
DO 400 I = 1, N
OLDNUM(I) = NEWNUM(I)
400 CONTINUE
GO TO 800
C
C ... CHECK NEW REVERSED ORDERING FOR BEST PROFILE
C
500 IF (NRVPRO .GT. OLDPRO) GO TO 700
BANDWD = NRVBND
PROFIL = NRVPRO
DO 600 I = 1, N
OLDNUM(I) = N - NEWNUM(I) + 1
IF (I .GT. N/2) GO TO 600
J = INVNUM(I)
NMIP1 = (N + 1) - I
INVNUM(I) = INVNUM (NMIP1)
INVNUM (NMIP1) = J
600 CONTINUE
GO TO 800
C
C
C ... RETAIN OLD ORDERING
C
700 BANDWD = OLDBND
PROFIL = OLDPRO
C
800 RETURN
C
C ------------------------------------------------------------------
C
6000 ERROR = 71
SPACE = -1
RETURN
C
END
SUBROUTINE GPSKCN (N, KEY, DATA, ERROR)
C
C ==================================================================
C
C I N S E R T I O N S O R T
C
C INPUT:
C N -- NUMBER OF ELEMENTS TO BE SORTED
C KEY -- AN ARRAY OF LENGTH N CONTAINING THE VALUES
C WHICH ARE TO BE SORTED
C DATA -- A SECOND ARRAY OF LENGTH N CONTAINING DATA
C ASSOCIATED WITH THE INDIVIDUAL KEYS.
C
C OUTPUT:
C KEY -- WILL BE ARRANGED SO THAT VALUES ARE IN DECREASING
C ORDER
C DATA -- REARRANGED TO CORRESPOND TO REARRANGED KEYS
C ERROR -- WILL BE ZERO UNLESS THE PROGRAM IS MALFUNCTIONING,
C IN WHICH CASE IT WILL BE EQUAL TO 1.
C
C
C ==================================================================
C
IMPLICIT INTEGER(I-N)
INTEGER N, ERROR
C
CIBM INTEGER *2 KEY(N), DATA(N)
INTEGER KEY(N), DATA(N)
C
C ------------------------------------------------------------------
C
INTEGER I, J, D, K, IP1, JM1
C
C ------------------------------------------------------------------
C
IF (N .EQ. 1) RETURN
IF (N .LE. 0) GO TO 6000
C
ERROR = 0
C
C ... INSERTION SORT ... FOR I := N-1 STEP -1 TO 1 DO ...
C
2400 I = N - 1
IP1 = N
C
2500 IF ( KEY (I) .GE. KEY (IP1) ) GO TO 2800
C
C ... OUT OF ORDER ... MOVE UP TO CORRECT PLACE
C
K = KEY (I)
D = DATA (I)
J = IP1
JM1 = I
C
C ... REPEAT ... UNTIL 'CORRECT PLACE FOR K FOUND'
C
2600 KEY (JM1) = KEY (J)
DATA (JM1) = DATA (J)
JM1 = J
J = J + 1
IF (J .GT. N) GO TO 2700
IF (KEY (J) .GT. K) GO TO 2600
C
2700 KEY (JM1) = K
DATA (JM1) = D
C
2800 IP1 = I
I = I - 1
IF ( I .GT. 0 ) GO TO 2500
C
3000 RETURN
C
6000 ERROR = 1
GO TO 3000
C
END
SUBROUTINE GPSKCO (N, KEY, ERROR)
C
C ==================================================================
C
C I N S E R T I O N S O R T
C
C INPUT:
C N -- NUMBER OF ELEMENTS TO BE SORTED
C KEY -- AN ARRAY OF LENGTH N CONTAINING THE VALUES
C WHICH ARE TO BE SORTED
C
C OUTPUT:
C KEY -- WILL BE ARRANGED SO THAT VALUES ARE IN DECREASING
C ORDER
C
C ==================================================================
C
IMPLICIT INTEGER(I-N)
INTEGER N, ERROR
C
CIBM INTEGER *2 KEY(N)
INTEGER KEY(N)
C
C ------------------------------------------------------------------
C
INTEGER I, J, K, IP1, JM1
C
C ------------------------------------------------------------------
C
IF (N .EQ. 1) RETURN
IF (N .LE. 0) GO TO 6000
C
ERROR = 0
C
C ... INSERTION SORT ... FOR I := N-1 STEP -1 TO 1 DO ...
C
2400 I = N - 1
IP1 = N
C
2500 IF ( KEY (I) .GE. KEY (IP1) ) GO TO 2800
C
C ... OUT OF ORDER ... MOVE UP TO CORRECT PLACE
C
K = KEY (I)
J = IP1
JM1 = I
C
C ... REPEAT ... UNTIL 'CORRECT PLACE FOR K FOUND'
C
2600 KEY (JM1) = KEY (J)
JM1 = J
J = J + 1
IF (J .GT. N) GO TO 2700
IF (KEY (J) .GT. K) GO TO 2600
C
2700 KEY (JM1) = K
C
2800 IP1 = I
I = I - 1
IF ( I .GT. 0 ) GO TO 2500
C
3000 RETURN
C
6000 ERROR = 1
GO TO 3000
C
END
SUBROUTINE GPSKCP (N, INDEX, NVEC, DEGREE, ERROR)
C
C ==================================================================
C
C I N S E R T I O N S O R T
C
C INPUT:
C N -- NUMBER OF ELEMENTS TO BE SORTED
C INDEX -- AN ARRAY OF LENGTH N CONTAINING THE INDICES
C WHOSE DEGREES ARE TO BE SORTED
C DEGREE -- AN NVEC VECTOR, GIVING THE DEGREES OF NODES
C WHICH ARE TO BE SORTED.
C
C OUTPUT:
C INDEX -- WILL BE ARRANGED SO THAT VALUES ARE IN DECREASING
C ORDER
C ERROR -- WILL BE ZERO UNLESS THE PROGRAM IS MALFUNCTIONING,
C IN WHICH CASE IT WILL BE EQUAL TO 1.
C
C ==================================================================
C
IMPLICIT INTEGER(I-N)
INTEGER N, NVEC, ERROR
C
CIBM INTEGER *2 INDEX(N), DEGREE(NVEC)
INTEGER INDEX(N), DEGREE(NVEC)
C
C ------------------------------------------------------------------
C
INTEGER I, J, V, IP1, JM1, INDEXI, INDXI1, INDEXJ
C
C ------------------------------------------------------------------
C
IF (N .EQ. 1) RETURN
IF (N .LE. 0) GO TO 6000
C
ERROR = 0
C
C ------------------------------------------------------------------
C INSERTION SORT THE ENTIRE FILE
C ------------------------------------------------------------------
C
C
C ... INSERTION SORT ... FOR I := N-1 STEP -1 TO 1 DO ...
C
2400 I = N - 1
IP1 = N
C
2500 INDEXI = INDEX (I)
INDXI1 = INDEX (IP1)
IF ( DEGREE(INDEXI) .GE. DEGREE(INDXI1) ) GO TO 2800
C
C ... OUT OF ORDER ... MOVE UP TO CORRECT PLACE
C
V = DEGREE (INDEXI)
J = IP1
JM1 = I
INDEXJ = INDEX (J)
C
C ... REPEAT ... UNTIL 'CORRECT PLACE FOR V FOUND'
C
2600 INDEX (JM1) = INDEXJ
JM1 = J
J = J + 1
IF (J .GT. N) GO TO 2700
INDEXJ = INDEX (J)
IF (DEGREE(INDEXJ) .GT. V) GO TO 2600
C
2700 INDEX (JM1) = INDEXI
C
2800 IP1 = I
I = I - 1
IF ( I .GT. 0 ) GO TO 2500
C
3000 RETURN
C
6000 ERROR = 1
GO TO 3000
C
END
SUBROUTINE GPSKCQ (N, INDEX, NVEC, DEGREE, ERROR)
C
C ==================================================================
C
C I N S E R T I O N S O R T
C
C INPUT:
C N -- NUMBER OF ELEMENTS TO BE SORTED
C INDEX -- AN ARRAY OF LENGTH N CONTAINING THE INDICES
C WHOSE DEGREES ARE TO BE SORTED
C DEGREE -- AN NVEC VECTOR, GIVING THE DEGREES OF NODES
C WHICH ARE TO BE SORTED.
C
C OUTPUT:
C INDEX -- WILL BE ARRANGED SO THAT VALUES ARE IN INCREASING
C ORDER
C ERROR -- WILL BE ZERO UNLESS THE PROGRAM IS MALFUNCTIONING,
C IN WHICH CASE IT WILL BE EQUAL TO 1.
C
C ==================================================================
C
IMPLICIT INTEGER(I-N)
INTEGER N, NVEC, ERROR
C
CIBM INTEGER *2 INDEX(N), DEGREE(NVEC)
INTEGER INDEX(N), DEGREE(NVEC)
C
C ------------------------------------------------------------------
C
INTEGER I, J, V, INDEXI, INDXI1, INDEXJ, IP1, JM1
C
C ------------------------------------------------------------------
C
IF (N .EQ. 1) RETURN
IF (N .LE. 0) GO TO 6000
C
ERROR = 0
C
C ------------------------------------------------------------------
C INSERTION SORT THE ENTIRE FILE
C ------------------------------------------------------------------
C
C
C ... INSERTION SORT ... FOR I := N-1 STEP -1 TO 1 DO ...
C
2400 I = N - 1
IP1 = N
C
2500 INDEXI = INDEX (I)
INDXI1 = INDEX (IP1)
IF ( DEGREE(INDEXI) .LE. DEGREE(INDXI1) ) GO TO 2800
C
C ... OUT OF ORDER ... MOVE UP TO CORRECT PLACE
C
V = DEGREE (INDEXI)
J = IP1
JM1 = I
INDEXJ = INDEX (J)
C
C ... REPEAT ... UNTIL 'CORRECT PLACE FOR V FOUND'
C
2600 INDEX (JM1) = INDEXJ
JM1 = J
J = J + 1
IF (J .GT. N) GO TO 2700
INDEXJ = INDEX (J)
IF (DEGREE(INDEXJ) .LT. V) GO TO 2600
C
2700 INDEX (JM1) = INDEXI
C
2800 IP1 = I
I = I - 1
IF ( I .GT. 0 ) GO TO 2500
C
3000 RETURN
C
6000 ERROR = 1
GO TO 3000
C
END
					© Cast3M 2003 - Tous droits réservés.
					Mentions légales