Télécharger gpskca.eso

Retour à la liste

Numérotation des lignes :

gpskca
  1. C GPSKCA SOURCE CB215821 22/11/16 21:15:02 11500
  2. C GPSKC SOURCE PV 18/06/18 21:15:05 9860
  3. C ALGORITHM 582, COLLECTED ALGORITHMS FROM ACM.
  4. C ALGORITHM APPEARED IN ACM-TRANS. MATH. SOFTWARE, VOL.8, NO. 2,
  5. C JUN., 1982, P. 190.
  6. C ==============================================================
  7. C
  8. C GIBBS-POOLE-STOCKMEYER AND GIBBS-KING ALGORITHMS ...
  9. C
  10. C 1. SUBROUTINES GPSKCA, GPSKCB, ..., GPSKCQ WHICH IMPLEMENT
  11. C GIBBS-POOLE-STOCKMEYER AND GIBBS-KING ALGORITHMS ...
  12. C
  13. C 2. SAMPLE DRIVER PROGRAM
  14. C
  15. C 3. SAMPLE TEST PROBLEMS
  16. C
  17. C 4. OUTPUT PRODUCED BY SAMPLE DRIVER ON SAMPLE TEST PROBLEMS
  18. C
  19. C ALL OF THE ABOVE ARE IN 80 COLUMN FORMAT. THE FIRST TWO
  20. C SECTIONS HAVE SEQUENCE NUMBERS IN COLUMNS 73 TO 80. THE
  21. C THIRD SECTION HAS DATA IN ALL 80 COLUMNS. THE LAST SECTION
  22. C HAS CARRIAGE CONTROL CHARACTERS IN COLUMN 1 AND DATA IN ALL
  23. C 80 COLUMNS.
  24. C
  25. C THESE FOUR SECTIONS OF THE FILE ARE SEPARATED BY SINGLE CARDS
  26. C OF THE FORM 'C === SEPARATOR ===' IN COLUMNS 1 TO 19
  27. C
  28. C ==============================================================
  29. C
  30. C THE SAMPLE TEST PROBLEMS INCLUDED WITH THIS CODE PROVIDE A
  31. C MINIMAL CHECKOUT OF THE FUNCTIONING OF THE CODE. THE TEST
  32. C PROBLEMS HAVE NUMERICAL VALUES WITH THE INTEGER PART BEING
  33. C THE ROW INDEX, THE FRACTIONAL PART THE COLUMN INDEX, OF THE
  34. C MATRIX AFTER GPS(K) REORDERING. THE TEST OUTPUT INCLUDES A
  35. C LISTING OF THE REORDERED MATRIX, IN WHICH THE NUMERIC VALUES
  36. C SHOULD APPEAR IN CORRECT POSITIONS, INTERMINGLED WITH ZEROES
  37. C WHICH REPRESENT FILL IN THE SPARSE MATRIX FACTORIZATION.
  38. C
  39. C ==============================================================
  40. C
  41. C === SEPARATOR === BEGINNING OF GPS AND GK ALGORITHMS
  42. SUBROUTINE GPSKCA (N, DEGREE, RSTART, CONNEC, OPTPRO, WRKLEN,
  43. 1 PERMUT, WORK, BANDWD, PROFIL, ERROR, SPACE)
  44. C
  45. C ==================================================================
  46. C ==================================================================
  47. C = =
  48. 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 =
  49. C = FOR A SPARSE AND (STRUCTURALLY) SYMMETRIC MATRIX, =
  50. C = USING EITHER =
  51. C = =
  52. C = THE GIBBS-POOLE-STOCKMEYER ALGORITHM (BANDWIDTH REDUCTION) =
  53. C = OR =
  54. C = THE GIBBS-KING ALGORITHM (PROFILE REDUCTION) =
  55. C = =
  56. C ==================================================================
  57. C ==================================================================
  58. C = THIS CODE SUPERSEDES TOMS ALGORITHMS 508 AND 509 IN THE =
  59. C = COLLECTED ALGORITHMS OF THE ACM (CALGO). =
  60. C ==================================================================
  61. C ==================================================================
  62. C
  63. C -------------------
  64. C P A R A M E T E R S
  65. C -------------------
  66. C
  67. IMPLICIT INTEGER(I-N)
  68. INTEGER N, RSTART(N), WRKLEN, BANDWD, PROFIL, ERROR, SPACE
  69. C
  70. CIBM INTEGER *2 DEGREE(N), CONNEC(1), PERMUT(N), WORK(WRKLEN)
  71. INTEGER DEGREE(N), CONNEC(1), PERMUT(N), WORK(WRKLEN)
  72. C
  73. LOGICAL OPTPRO
  74. C
  75. C ------------------------------------------------------------------
  76. C
  77. C INPUT PARAMETERS:
  78. C ----- ----------
  79. C
  80. C N -- THE DIMENSION OF THE MATRIX
  81. C
  82. C DEGREE,
  83. C RSTART,
  84. C CONNEC -- DESCRIBE THE STRUCTURE OF THE SPARSE MATRIX.
  85. C DEGREE(I) SPECIFIES THE NUMBER OF NON-ZERO
  86. C OFF-DIAGONAL ENTRIES IN THE I-TH ROW OF THE
  87. C SPARSE MATRIX. THE COLUMN INDICES OF THESE
  88. C ENTRIES ARE GIVEN IN CONSECUTIVE LOCATIONS IN
  89. C CONNEC, STARTING AT LOCATION RSTART(I).
  90. C IN OTHER WORDS, THE INDICES OF THE NON-ZERO
  91. C OFF-DIAGONAL ELEMENTS OF THE I-TH ROW ARE FOUND
  92. C IN:
  93. C CONNEC (RSTART(I)),
  94. C CONNEC (RSTART(I) + 1),
  95. C . . .
  96. C CONNEC (RSTART(I) + DEGREE(I) - 1)
  97. C
  98. C DIMENSIONS:
  99. C RSTART IS DIMENSION N (OR LONGER).
  100. C DEGREE IS DIMENSION N (OR LONGER).
  101. C CONNEC IS DIMENSION ROUGHLY THE NUMBER OF NON-
  102. C ZERO ENTRIES IN THE MATRIX.
  103. C
  104. C OPTPRO -- .TRUE. IF REDUCING THE PROFILE OF THE MATRIX
  105. C IS MORE IMPORTANT THAN REDUCING THE
  106. C BANDWIDTH
  107. C .FALSE. IF BANDWIDTH REDUCTION IS MOST IMPORTANT
  108. C
  109. C WRKLEN -- THE ACTUAL LENGTH OF THE VECTOR WORK AS SUPPLIED
  110. C BY THE USER. SEE THE DISCUSSION OF THE WORKSPACE
  111. C 'WORK' BELOW FOR TYPICAL STORAGE REQUIREMENTS.
  112. C THE VALUE OF WRKLEN WILL BE USED TO ENSURE THAT
  113. C THE ROUTINE WILL NOT USE MORE STORAGE THAN IS
  114. C AVAILABLE. IF NOT ENOUGH SPACE IS GIVEN IN WORK
  115. C TO PERMIT A SOLUTION TO BE FOUND, THE ERROR FLAG
  116. C WILL BE SET AND FURTHER COMPUTATION STOPPED.
  117. C
  118. C
  119. C INPUT AND OUTPUT PARAMETER:
  120. C ----- --- ------ ---------
  121. C
  122. C PERMUT -- ON INPUT, AN ALTERNATIVE REORDERING FOR THE
  123. C ROWS AND COLUMNS OF THE MATRIX. PERMUT(I) GIVES
  124. C THE POSITION IN WHICH ROW AND COLUMN I SHOULD
  125. C BE PLACED TO REDUCE THE BANDWIDTH OR THE PROFILE.
  126. C IF THE USER HAS NO ALTERNATIVE TO THE NATURAL
  127. C HE SHOULD INITIALIZE PERMUT TO BE THE IDENTITY
  128. C PERMUTATION PERMUT(I) = I .
  129. C
  130. C ON OUTPUT, PERMUT WILL CONTAIN THE PERMUTATION
  131. C FOR REORDERING THE ROWS AND COLUMNS WHICH REDUCES
  132. C THE BANDWIDTH AND/OR PROFILE. THE RESULT WILL BE
  133. C THE REORDERING FOUND BY 'GPSKCA' OR THE REORDERING
  134. C GIVEN BY THE USER IN 'PERMUT', WHICHEVER DOES THE
  135. C JOB BETTER.
  136. C
  137. C
  138. C OUTPUT PARAMETERS:
  139. C ------ ----------
  140. C
  141. C WORK -- A TEMPORARY STORAGE VECTOR, OF LENGTH SOMEWHAT
  142. C GREATER THAN 3N. THE SPACE BEYOND 3N REQUIRED
  143. C IS PROBLEM-DEPENDENT. ANY PROBLEM CAN BE SOLVED
  144. C IN 6N+3 LOCATIONS.
  145. C MOST PROBLEMS CAN BE REORDERED WITH 4N LOCATIONS
  146. C IN 'WORK'. IF SPACE IS NOT A CONSTRAINT, PROVIDE
  147. C 6N+3 LOCATIONS IN 'WORK'. OTHERWISE, PROVIDE AS
  148. C MUCH MORE THAN 3N AS IS CONVENIENT AND CHECK THE
  149. C ERROR FLAG AND SPACE REQUIRED PARAMETERS (SEE BELOW)
  150. C
  151. C ON OUTPUT, THE 1ST N LOCATIONS OF WORK WILL BE
  152. C A LISTING OF THE ORIGINAL ROW AND COLUMN INDICES AS
  153. C THEY APPEAR IN THE COMPUTED REORDERING.
  154. C LOCATIONS N+1, ... , 2N OF WORK WILL CONTAIN
  155. C THE NEW POSITIONS FOR THE EQUATIONS IN THE ORDER
  156. C FOUND BY GPSKCA. THUS, THE TWO VECTORS ARE INVERSE
  157. C PERMUTATIONS OF EACH OTHER. IF THE ORDERING
  158. C FOUND BY THIS ALGORITHM IS BETTER THAN THE USER-
  159. C SUPPLIED ORDER, THE SECOND PERMUTATION VECTOR IS
  160. C IDENTICAL TO THE RESULT RETURNED IN 'PERMUT'.
  161. C
  162. C BANDWD -- THE BANDWIDTH OF THE MATRIX WHEN ROWS AND COLUMNS
  163. C ARE REORDERED IN THE ORDERING RETURNED IN PERMUT.
  164. C
  165. C PROFIL -- THE PROFILE OF THE MATRIX WHEN ROWS AND COLUMNS ARE
  166. C REORDERED IN THE ORDERING RETURNED IN PERMUT.
  167. C
  168. C ERROR -- WILL BE EQUAL TO ZERO IF A NEW NUMBERING COULD BE
  169. C FOUND IN THE SPACE PROVIDED. OTHERWISE, ERROR
  170. C WILL BE SET TO A POSITIVE ERROR CODE (SEE TABLE
  171. C GIVEN BELOW). IF THE REORDERING ALGORITHM HAS BEEN
  172. C STOPPED BY LACK OF WORKSPACE, THE SPACE PARAMETER
  173. C WILL BE SET TO THE NUMBER OF ADDITIONAL LOCATIONS
  174. C REQUIRED TO COMPLETE AT LEAST THE NEXT PHASE OF
  175. C THE ALGORITHM.
  176. C
  177. C WHENEVER A NON-ZERO VALUE FOR ERROR IS GIVEN
  178. C PERMUT WILL RETAIN THE VALUES PROVIDED BY THE USER
  179. C AND THE SCALARS BANDWD AND PROFIL WILL BE SET TO
  180. C OUTRAGEOUS VALUES. IT IS THE USER'S RESPONSIBILITY
  181. C TO CHECK THE STATUS OF ERROR.
  182. C
  183. C SPACE -- WILL INDICATE EITHER HOW MUCH SPACE THE REORDERING
  184. C ACTUALLY REQUIRED OR HOW MUCH SPACE WILL BE
  185. C REQUIRED TO COMPLETE THE NEXT PHASE OF THE
  186. C REORDERING ALGORITHM. THE POSSIBLE OUTCOMES ARE ..
  187. C
  188. C ERROR = 0 SPACE IS THE MINIMAL VALUE FOR
  189. C WRKLEN REQUIRED TO REORDER
  190. C THIS MATRIX AGAIN.
  191. C
  192. C ERROR <> 0 SPACE IS THE MINIMUM NUMBER
  193. C DUE TO LACK OF OF EXTRA WORKSPACE REQUIRED
  194. C WORKSPACE TO CONTINUE THE REORDERING
  195. C ALGORITHM ON THIS MATRIX.
  196. C
  197. C ERROR <> 0 SPACE = -1
  198. C DUE TO ERROR
  199. C IN DATA STRUCTURES
  200. C
  201. C
  202. C ==================================================================
  203. C
  204. C ----------------------
  205. C E R R O R C O D E S
  206. C ----------------------
  207. C
  208. C ERROR CODES HAVE THE FORM 0XY OR 1XY.
  209. C
  210. C ERRORS OF THE FORM 1XY RESULT FROM INADEQUATE WORKSPACE.
  211. C
  212. C ERRORS OF THE FORM 0XY ARE INTERNAL PROGRAM CHECKS, WHICH
  213. C MOST LIKELY OCCUR BECAUSE THE CONNECTIVITY STRUCTURE OF THE
  214. C MATRIX IS REPRESENTED INCORRECTLY (E.G., THE DEGREE OF
  215. C A NODE IS NOT CORRECT OR NODE I IS CONNECTED TO NODE J,
  216. C BUT NOT CONVERSELY).
  217. C
  218. C THE LAST DIGIT (Y) IS MAINLY USEFUL FOR DEBUGGING THE
  219. C THE REORDERING ALGORITHM. THE MIDDLE DIGIT (X) INDICATES
  220. C HOW MUCH OF THE ALGORITHM HAS BEEN PERFORMED.
  221. C THE TABLE BELOW GIVES THE CORRESPONDENCE BETWEEN THE
  222. C VALUES OF X AND THE STRUCTURE OF THE ALGORITHM.
  223. C X = 0 INITIAL PROCESSING
  224. C X = 1 COMPUTING PSEUDO-DIAMETER (ALGORITHM I)
  225. C X = 2 TRANSITION BETWEEN ALGORITHM I AND II
  226. C X = 3 COMBINING LEVEL STRUCTURES (ALGORITHM II)
  227. C X = 4 TRANSITION BETWEEN ALGORITHM II AND III
  228. C X = 5 BANDWIDTH NUMBERING (ALGORITHM IIIA)
  229. C X = 6 PROFILE NUMBERING (ALGORITHM IIIB)
  230. C X = 7 FINAL BANDWIDTH/PROFILE COMPUTATION
  231. C
  232. C ==================================================================
  233. C
  234. C --------------------- ---------------
  235. C A L T E R N A T I V E V E R S I O N S
  236. C --------------------- ---------------
  237. C
  238. C SHORT INTEGER VERSION
  239. C
  240. C ON MACHINES WITH TWO OR MORE PRECISIONS FOR INTEGERS,
  241. C ALL OF THE INPUT ARRAYS EXCEPT 'RSTART' CAN BE CONVERTED
  242. C TO THE SHORTER PRECISION AS LONG AS THAT SHORTER PRECISION
  243. C ALLOWS NUMBERS AS LARGE AS 'N'. A VERSION OF THIS CODE
  244. C SUITABLE FOR USE ON IBM COMPUTERS (INTEGER * 2) IS EMBEDDED
  245. C AS COMMENTS IN THIS CODE. ALL SUCH COMMENTS HAVE THE
  246. C CHARACTERS 'CIBM' IN THE FIRST FOUR COLUMNS, AND PRECEDE THE
  247. C EQUIVALENT STANDARD CODE WHICH THEY WOULD REPLACE.
  248. C
  249. C CONNECTIVITY COMPATIBILITY VERSION
  250. C
  251. C THE ORIGINAL (1976) TOMS CODE 'REDUCE' USED A LESS STORAGE
  252. C EFFICIENT FORMAT FOR THE CONNECTIVITY TABLE 'CONNEC'.
  253. C THE 1976 CODE USED A RECTANGULAR MATRIX OF DIMENSIONS
  254. C N BY MAXDGR, WHERE MAXDGR IS AT LEAST AS LARGE AS
  255. C THE MAXIMUM DEGREE OF ANY NODE IN THE GRAPH OF THE MATRIX.
  256. C THE FORMAT USED IN THE CURRENT CODE IS OFTEN SUBSTANTIALLY
  257. C MORE EFFICIENT. HOWEVER, FOR USERS FOR WHOM CONVERSION WILL
  258. C BE DIFFICULT OR IMPOSSIBLE, TWO ALTERNATIVES ARE ..
  259. C 1. SIMPLY NOTE THAT CHANGING THE ORDER OF SUBSCRIPTS
  260. C IN A RECTANGULAR CONNECTION TABLE WILL ENABLE YOU
  261. C TO USE THE NEW VERSION. THIS SUBROUTINE WILL ACCEPT A
  262. C RECTANGULAR CONNECTION TABLE OF DIMENSIONS
  263. C MAXDGR BY N,
  264. C PROVIDED THAT RSTART(I) IS SET TO (I-1)*MAXDGR + 1.
  265. C 2. THE AUTHOR WILL MAKE AVAILABLE A VARIANT VERSION
  266. C 'GPSKRA', WHICH EXPECTS THE ADJACENCY MATRIX OR
  267. C CONNECTIVITY TABLE IN THE SAME FORM AS DID 'REDUCE'.
  268. C THIS VERSION CAN BE OBTAINED BY WRITING TO ..
  269. C JOHN GREGG LEWIS
  270. C BOEING COMPUTER SERVICES COMPANY
  271. C MAIL STOP 9C-01
  272. C P.O. BOX 24346
  273. C SEATTLE, WA 98124
  274. C PLEASE INCLUDE A DESCRIPTION OF THE COMPUTING
  275. C ENVIRONMENT ON WHICH YOU WILL BE USING THE CODE.
  276. C
  277. C ==================================================================
  278. C
  279. INTEGER I, INC1, INC2, AVAIL, NXTNUM, LOWDG, STNODE, NLEFT,
  280. 1 TREE1, TREE2, DEPTH, EMPTY, STOTAL, REQD, CSPACE,
  281. 2 LVLLST, LVLPTR, ACTIVE, RVNODE, WIDTH1, WIDTH2, MXDG
  282. C
  283. LOGICAL REVRS1, ONEIS1
  284. C
  285. C ==================================================================
  286. C
  287. C << NUMBER ANY DEGREE ZERO NODES >>
  288. C
  289. C WHILE << SOME NODES YET UNNUMBERED >> DO
  290. C << FIND A PSEUDO-DIAMETER OF THE MATRIX GRAPH >>
  291. C << CONVERT FORM OF LEVEL TREES >>
  292. C << COMBINE LEVEL TREES INTO ONE LEVEL STRUCTURE >>
  293. C << CONVERT FORM OF LEVEL STRUCTURE >>
  294. C IF OPTPRO THEN
  295. C << RENUMBER BY KING ALGORITHM >>
  296. C ELSE
  297. C << RENUMBER BY REVERSE CUTHILL-MCKEE ALGORITHM >>
  298. C
  299. C ==================================================================
  300. C
  301. C ... INITIALIZE COUNTERS, THEN NUMBER ANY NODES OF DEGREE 0.
  302. C THE LIST OF NODES, BY NEW NUMBER, WILL BE BUILT IN PLACE AT
  303. C THE FRONT OF THE WORK AREA.
  304. C
  305. NXTNUM = 1
  306. ERROR = 0
  307. SPACE = 2*N
  308. C
  309. MXDG = 0
  310. DO 300 I = 1, N
  311. IF (DEGREE(I)) 6000, 100, 200
  312. 100 WORK(NXTNUM) = I
  313. NXTNUM = NXTNUM + 1
  314. GO TO 300
  315. 200 IF (DEGREE(I) .GT. MXDG) MXDG = DEGREE(I)
  316. 300 CONTINUE
  317. C
  318. C
  319. C ==============================
  320. C ... WHILE NXTNUM <= N DO ...
  321. C ==============================
  322. C
  323. 1000 IF ( NXTNUM .GT. N ) GO TO 2000
  324. C
  325. C ... FIND AN UNNUMBERED NODE OF MINIMAL DEGREE
  326. C
  327. LOWDG = MXDG + 1
  328. STNODE = 0
  329. DO 400 I = 1, N
  330. IF ( (DEGREE(I) .LE. 0) .OR. (DEGREE(I) .GE. LOWDG) )
  331. 1 GO TO 400
  332. LOWDG = DEGREE(I)
  333. STNODE = I
  334. 400 CONTINUE
  335. C
  336. IF ( STNODE .EQ. 0 ) GO TO 6100
  337. C
  338. C ... SET UP POINTERS FOR THREE LISTS IN WORK AREA, THEN LOOK
  339. C FOR PSEUDO-DIAMETER, BEGINNING WITH STNODE.
  340. C
  341. AVAIL = (WRKLEN - NXTNUM + 1) / 3
  342. NLEFT = N - NXTNUM + 1
  343. SPACE = MAX0 (SPACE, NXTNUM + 3*N - 1)
  344. IF ( AVAIL .LT. N ) GO TO 5200
  345. C
  346. CALL GPSKCB (N, DEGREE, RSTART, CONNEC, AVAIL, NLEFT,
  347. 1 STNODE, RVNODE, WORK(NXTNUM), TREE1, TREE2,
  348. 2 ACTIVE, DEPTH, WIDTH1, WIDTH2,
  349. 3 ERROR, SPACE)
  350. IF ( ERROR .NE. 0 ) GO TO 5000
  351. SPACE = MAX0 (SPACE, NXTNUM + 3*(ACTIVE+DEPTH+1) - 1)
  352. C
  353. C ... DYNAMIC SPACE CHECK FOR MOST OF REMAINDER OF ALGORITHM
  354. C
  355. REQD = MAX0 (NXTNUM + 2*N + 3*DEPTH - 1, 3*N + 2*DEPTH + 1)
  356. SPACE = MAX0 (SPACE, REQD)
  357. IF ( WRKLEN .LT. REQD ) GO TO 5300
  358. C
  359. C
  360. C ... OUTPUT FROM GPSKCB IS A PAIR OF LEVEL TREES, IN THE FORM
  361. C OF LISTS OF NODES BY LEVEL. CONVERT THIS TO TWO LISTS OF
  362. C OF LEVEL NUMBER BY NODE. AT THE SAME TIME PACK
  363. C STORAGE SO THAT ONE OF THE LEVEL TREE VECTORS IS AT THE
  364. C BACK END OF THE WORK AREA.
  365. C
  366. LVLPTR = NXTNUM + AVAIL - DEPTH
  367. CALL GPSKCE (N, AVAIL, ACTIVE, DEPTH, WRKLEN, WORK(NXTNUM),
  368. 1 WORK(LVLPTR), WORK(1), NXTNUM, TREE1,
  369. 2 TREE2, WIDTH1, WIDTH2, ONEIS1, ERROR, SPACE)
  370. IF ( ERROR .NE. 0 ) GO TO 5000
  371. IF (( TREE1 .NE. WRKLEN - N + 1 ) .OR. (TREE2 .NE. NXTNUM))
  372. 1 GO TO 6200
  373. C
  374. C ... COMBINE THE TWO LEVEL TREES INTO A MORE GENERAL
  375. C LEVEL STRUCTURE.
  376. C
  377. AVAIL = WRKLEN - NXTNUM + 1 - 2*N - 3*DEPTH
  378. STOTAL = N + NXTNUM
  379. EMPTY = STOTAL + DEPTH
  380. INC1 = TREE1 - DEPTH
  381. INC2 = INC1 - DEPTH
  382. C
  383. CALL GPSKCG (N, DEGREE, RSTART, CONNEC, ACTIVE, WIDTH1,
  384. 1 WIDTH2, WORK(TREE1), WORK(TREE2), WORK(EMPTY),
  385. 2 AVAIL, DEPTH, WORK(INC1), WORK(INC2),
  386. 3 WORK(STOTAL), ONEIS1, REVRS1, ERROR, CSPACE)
  387. C
  388. IF ( ERROR .NE. 0 ) GO TO 5000
  389. SPACE = MAX0 (SPACE, NXTNUM + CSPACE - 1)
  390. C
  391. C ... COMBINED LEVEL STRUCTURE IS REPRESENTED BY GPSKCG AS
  392. C A VECTOR OF LEVEL NUMBERS. FOR RENUMBERING PHASE,
  393. C CONVERT THIS ALSO TO THE INVERSE PERMUTATION.
  394. C
  395. LVLPTR = TREE1 - (DEPTH + 1)
  396. LVLLST = LVLPTR - ACTIVE
  397. IF ( STOTAL + DEPTH .GT. LVLPTR ) GO TO 6300
  398. C
  399. CALL GPSKCI (N, ACTIVE, DEPTH, WORK(TREE1), WORK(LVLLST),
  400. 1 WORK(LVLPTR), WORK(STOTAL), ERROR, SPACE)
  401. IF (ERROR .NE. 0) GO TO 5000
  402. C
  403. C ... NOW RENUMBER ALL MEMBERS OF THIS COMPONENT USING
  404. C EITHER A REVERSE CUTHILL-MCKEE OR A KING STRATEGY,
  405. C AS PROFILE OR BANDWIDTH REDUCTION IS MORE IMPORTANT.
  406. C
  407. IF ( OPTPRO ) GO TO 500
  408. CALL GPSKCJ (N, DEGREE, RSTART, CONNEC, ACTIVE,
  409. 1 WORK(NXTNUM), STNODE, RVNODE, REVRS1, DEPTH,
  410. 2 WORK(LVLLST), WORK(LVLPTR), WORK(TREE1),
  411. 3 ERROR, SPACE)
  412. IF ( ERROR .NE. 0 ) GO TO 5000
  413. NXTNUM = NXTNUM + ACTIVE
  414. GO TO 600
  415. C
  416. 500 CALL GPSKCK (N, DEGREE, RSTART, CONNEC, LVLLST-1, NXTNUM,
  417. 1 WORK, ACTIVE, DEPTH, WORK(LVLLST),
  418. 2 WORK(LVLPTR), WORK(TREE1), ERROR, SPACE)
  419. IF ( ERROR .NE. 0 ) GO TO 5000
  420. C
  421. C =========================================================
  422. C ... END OF WHILE LOOP ... REPEAT IF GRAPH IS DISCONNECTED
  423. C =========================================================
  424. C
  425. 600 GO TO 1000
  426. C
  427. C ... CHECK WHETHER INITIAL NUMBERING OR FINAL NUMBERING
  428. C PROVIDES BETTER RESULTS
  429. C
  430. 2000 IF (WRKLEN .LT. 2*N) GO TO 5400
  431. C
  432. IF (OPTPRO) GO TO 2100
  433. CALL GPSKCL (N, DEGREE, RSTART, CONNEC, WORK(1), WORK(N+1),
  434. 1 PERMUT, BANDWD, PROFIL, ERROR, SPACE)
  435. GO TO 2200
  436. C
  437. 2100 CALL GPSKCM (N, DEGREE, RSTART, CONNEC, WORK(1), WORK(N+1),
  438. 1 PERMUT, BANDWD, PROFIL, ERROR, SPACE)
  439. C
  440. 2200 RETURN
  441. C
  442. C
  443. C . . . E R R O R D I A G N O S T I C S
  444. C ---------------------------------
  445. C
  446. C ... ERROR DETECTED BY LOWER LEVEL ROUTINE. MAKE SURE THAT SIGNS
  447. C OF DEGREE ARE PROPERLY SET
  448. C
  449. 5000 DO 5100 I = 1, N
  450. IF (DEGREE(I) .LT. 0) DEGREE(I) = -DEGREE(I)
  451. 5100 CONTINUE
  452. C
  453. BANDWD = -1
  454. PROFIL = -1
  455. RETURN
  456. C
  457. C ... STORAGE ALLOCATION ERRORS DETECTED IN THIS ROUTINE
  458. C
  459. 5200 ERROR = 101
  460. SPACE = -1
  461. GO TO 5000
  462. C
  463. 5300 ERROR = 102
  464. SPACE = -1
  465. GO TO 5000
  466. C
  467. 5400 ERROR = 10
  468. SPACE = 2*N - WRKLEN
  469. GO TO 5000
  470. C
  471. C ... DATA STRUCTURE ERRORS DETECTED IN THIS ROUTINE
  472. C
  473. 6000 ERROR = 1
  474. GO TO 6900
  475. C
  476. 6100 ERROR = 2
  477. GO TO 6900
  478. C
  479. 6200 ERROR = 3
  480. GO TO 6900
  481. C
  482. 6300 ERROR = 4
  483. C
  484. 6900 SPACE = -1
  485. GO TO 5000
  486. END
  487. SUBROUTINE GPSKCB (N, DEGREE, RSTART, CONNEC, AVAIL, NLEFT,
  488. 1 STNODE, RVNODE, WORK, FORWD, BESTBK, NNODES,
  489. 2 DEPTH, FWIDTH, BWIDTH, ERROR, SPACE)
  490. C
  491. C ==================================================================
  492. C
  493. C FIND A PSEUDO-DIAMETER OF THE MATRIX GRAPH ...
  494. C
  495. C << BUILD A LEVEL TREE FROM STNODE >>
  496. C REPEAT
  497. C << BUILD A LEVEL TREE FROM EACH NODE 'BKNODE' IN THE
  498. C DEEPEST LEVEL OF STNODE'S TREE >>
  499. C << REPLACE 'STNODE' WITH 'BKNODE' IF A DEEPER AND
  500. C NARROWER TREE WAS FOUND. >>
  501. C UNTIL
  502. C << NO FURTHER IMPROVEMENT MADE >>
  503. C
  504. C ... HEURISTIC ABOVE DIFFERS FROM THE ALGORITHM PUBLISHED IN
  505. C SIAM J. NUMERICAL ANALYSIS, BUT MATCHES THE CODE
  506. C DISTRIBUTED BY TOMS.
  507. C
  508. C
  509. C PARAMETERS :
  510. C
  511. C N, DEGREE, RSTART & CONNEC DESCRIBE THE MATRIX STRUCTURE
  512. C
  513. C WORK -- WORKING SPACE, OF LENGTH 3*AVAIL, USED TO STORE
  514. C THREE LEVEL TREES.
  515. C
  516. C STNODE IS INITIALLY THE NUMBER OF A NODE TO BE USED TO
  517. C START THE PROCESS, TO BE THE ROOT OF THE FIRST TREE.
  518. C ON OUTPUT, STNODE IS THE END OF THE PSEUDO-DIAMETER WHOSE
  519. C LEVEL TREE IS NARROWEST.
  520. C
  521. C RVNODE WILL BE THE OTHER END OF THE PSEUDO-DIAMETER.
  522. C
  523. C NNODES WILL BE THE NUMBER OF NODES IN THIS CONNECTED
  524. C COMPONNENT OF THE MATRIX GRAPH, I.E., THE LENGTH OF
  525. C THE LEVEL TREES.
  526. C
  527. C DEPTH -- THE DEPTH OF THE LEVEL TREES BEING RETURNED,
  528. C I.E., THE LENGTH OF THE PSEUDO-DIAMETER.
  529. C
  530. C ==================================================================
  531. C
  532. C STRUCTURE OF WORKSPACE ...
  533. C
  534. C ---------------------------------------------------------------
  535. C : NUMBERED : TLIST1 PTR1 : TLIST2 PTR2 : TLIST3 PTR3 :
  536. C ---------------------------------------------------------------
  537. C
  538. C TLISTI IS A LIST OF NODES OF LENGTH 'ACTIVE'
  539. C PTRI IS A LIST OF POINTERS INTO TLISTI, OF LENGTH 'DEPTH+1'
  540. C
  541. C ==================================================================
  542. C
  543. IMPLICIT INTEGER(I-N)
  544. INTEGER N, RSTART(N), AVAIL, NLEFT,
  545. 1 STNODE, RVNODE, FORWD, BESTBK, NNODES, DEPTH, FWIDTH,
  546. 4 BWIDTH, ERROR, SPACE
  547. C
  548. CIBM INTEGER *2 DEGREE(N), CONNEC(1), WORK(AVAIL,3)
  549. INTEGER DEGREE(N), CONNEC(1), WORK(AVAIL,3)
  550. C
  551. C ----------------
  552. C
  553. INTEGER BACKWD, MXDPTH, WIDTH, FDEPTH, LSTLVL,
  554. 1 NLAST, T, I, BKNODE, LSTLVI
  555. C
  556. LOGICAL IMPROV
  557. C
  558. C
  559. C ... BUILD INITIAL LEVEL TREE FROM 'STNODE'. FIND OUT HOW MANY
  560. C NODES LIE IN THE CURRENT CONNECTED COMPONENT.
  561. C
  562. FORWD = 1
  563. BACKWD = 2
  564. BESTBK = 3
  565. C
  566. CALL GPSKCC (N, DEGREE, RSTART, CONNEC, STNODE, AVAIL, NLEFT,
  567. 1 WORK(1,FORWD), NNODES, DEPTH, WIDTH, ERROR,
  568. 2 SPACE)
  569. IF ( ERROR .NE. 0 ) GO TO 5000
  570. C
  571. MXDPTH = AVAIL - NNODES - 1
  572. C
  573. C ==========================================
  574. C REPEAT UNTIL NO DEEPER TREES ARE FOUND ...
  575. C ==========================================
  576. C
  577. 1000 FWIDTH = WIDTH
  578. FDEPTH = DEPTH
  579. LSTLVL = AVAIL - DEPTH + 1
  580. NLAST = WORK (LSTLVL-1, FORWD) - WORK (LSTLVL, FORWD)
  581. LSTLVL = WORK (LSTLVL, FORWD)
  582. BWIDTH = N+1
  583. C
  584. C ... SORT THE DEEPEST LEVEL OF 'FORWD' TREE INTO INCREASING
  585. C ORDER OF NODE DEGREE.
  586. C
  587. CALL GPSKCQ (NLAST, WORK(LSTLVL,FORWD), N, DEGREE, ERROR)
  588. IF (ERROR .NE. 0) GO TO 6000
  589. C
  590. C ... BUILD LEVEL TREE FROM NODES IN 'LSTLVL' UNTIL A DEEPER
  591. C AND NARROWER TREE IS FOUND OR THE LIST IS EXHAUSTED.
  592. C
  593. IMPROV = .FALSE.
  594. DO 1200 I = 1, NLAST
  595. LSTLVI = LSTLVL + I - 1
  596. BKNODE = WORK (LSTLVI, FORWD)
  597. CALL GPSKCD (N, DEGREE, RSTART, CONNEC, BKNODE, AVAIL,
  598. 1 NNODES, MXDPTH, WORK(1,BACKWD), DEPTH, WIDTH,
  599. 2 BWIDTH, ERROR, SPACE)
  600. IF ( ERROR .NE. 0 ) GO TO 5000
  601. C
  602. IF ( DEPTH .LE. FDEPTH ) GO TO 1100
  603. C
  604. C ... NEW DEEPER TREE ... MAKE IT NEW 'FORWD' TREE
  605. C AND BREAK OUT OF 'DO' LOOP.
  606. C
  607. IMPROV = .TRUE.
  608. T = FORWD
  609. FORWD = BACKWD
  610. BACKWD = T
  611. STNODE = BKNODE
  612. GO TO 1300
  613. C
  614. C ... ELSE CHECK FOR NARROWER TREE.
  615. C
  616. 1100 IF ( WIDTH .GE. BWIDTH ) GO TO 1200
  617. T = BESTBK
  618. BESTBK = BACKWD
  619. BACKWD = T
  620. BWIDTH = WIDTH
  621. RVNODE = BKNODE
  622. 1200 CONTINUE
  623. C
  624. C ... END OF REPEAT LOOP
  625. C ----------------------
  626. C
  627. 1300 IF ( IMPROV ) GO TO 1000
  628. C
  629. DEPTH = FDEPTH
  630. RETURN
  631. C
  632. C ... IN CASE OF ERROR, SIMPLY RETURN ERROR FLAG TO USER.
  633. C
  634. 5000 RETURN
  635. C
  636. 6000 ERROR = 11
  637. SPACE = -1
  638. RETURN
  639. C
  640. END
  641. SUBROUTINE GPSKCC (N, DEGREE, RSTART, CONNEC, STNODE, AVAIL,
  642. 1 NLEFT, LIST, ACTIVE, DEPTH, WIDTH, ERROR,
  643. 2 SPACE)
  644. C
  645. C ==================================================================
  646. C BUILD THE LEVEL TREE ROOTED AT 'STNODE' IN THE SPACE PROVIDED IN
  647. C LIST. CHECK FOR OVERRUN OF SPACE ALLOCATION.
  648. C ==================================================================
  649. C
  650. IMPLICIT INTEGER(I-N)
  651. INTEGER N, RSTART(N), STNODE, AVAIL, NLEFT,
  652. 1 ACTIVE, DEPTH, WIDTH, ERROR, SPACE
  653. C
  654. CIBM INTEGER *2 DEGREE(N), CONNEC(1), LIST(AVAIL)
  655. INTEGER DEGREE(N), CONNEC(1), LIST(AVAIL)
  656. C
  657. C ... PARAMETERS:
  658. C
  659. C INPUT ...
  660. C
  661. C N, DEGREE, RSTART, CONNEC -- DESCRIBE THE MATRIX STRUCTURE
  662. C
  663. C STNODE -- THE ROOT OF THE LEVEL TREE.
  664. C
  665. C AVAIL -- THE LENGTH OF THE WORKING SPACE AVAILABLE
  666. C
  667. C NLEFT -- THE NUMBER OF NODES YET TO BE NUMBERED
  668. C
  669. C LIST -- THE WORKING SPACE.
  670. C
  671. C OUTPUT ...
  672. C
  673. C ACTIVE -- THE NUMBER OF NODES IN THE COMPONENT
  674. C
  675. C DEPTH -- THE DEPTH OF THE LEVEL TREE ROOTED AT STNODE.
  676. C
  677. C WIDTH -- THE WIDTH OF THE LEVEL TREE ROOTED AT STNODE.
  678. C
  679. C ERROR -- ZERO UNLESS STORAGE WAS INSUFFICIENT.
  680. C
  681. C ------------------------------------------------------------------
  682. C
  683. INTEGER LSTART, NLEVEL, FRONT, J, NEWNOD, PTR, CDGREE,
  684. 1 LFRONT, LISTJ
  685. C
  686. C ... BUILD THE LEVEL TREE USING LIST AS A QUEUE AND LEAVING
  687. C THE NODES IN PLACE. THIS GENERATES THE NODES ORDERED BY LEVEL
  688. C PUT POINTERS TO THE BEGINNING OF EACH LEVEL, BUILDING FROM
  689. C THE BACK OF THE WORK AREA.
  690. C
  691. ACTIVE = 1
  692. DEPTH = 0
  693. WIDTH = 0
  694. ERROR = 0
  695. LSTART = 1
  696. FRONT = 1
  697. LIST (ACTIVE) = STNODE
  698. DEGREE (STNODE) = -DEGREE (STNODE)
  699. LIST (AVAIL) = 1
  700. NLEVEL = AVAIL
  701. C
  702. C ... REPEAT UNTIL QUEUE BECOMES EMPTY OR WE RUN OUT OF SPACE.
  703. C ------------------------------------------------------------
  704. C
  705. 1000 IF ( FRONT .LT. LSTART ) GO TO 1100
  706. C
  707. C ... FIRST NODE OF LEVEL. UPDATE POINTERS.
  708. C
  709. LSTART = ACTIVE + 1
  710. WIDTH = MAX0 (WIDTH, LSTART - LIST(NLEVEL))
  711. NLEVEL = NLEVEL - 1
  712. DEPTH = DEPTH + 1
  713. IF ( NLEVEL .LE. ACTIVE ) GO TO 5000
  714. LIST (NLEVEL) = LSTART
  715. C
  716. C ... FIND ALL NEIGHBORS OF CURRENT NODE, ADD THEM TO QUEUE.
  717. C
  718. 1100 LFRONT = LIST (FRONT)
  719. PTR = RSTART (LFRONT)
  720. CDGREE = -DEGREE (LFRONT)
  721. IF (CDGREE .LE. 0) GO TO 6000
  722. DO 1200 J = 1, CDGREE
  723. NEWNOD = CONNEC (PTR)
  724. PTR = PTR + 1
  725. C
  726. C ... ADD TO QUEUE ONLY NODES NOT ALREADY IN QUEUE
  727. C
  728. IF ( DEGREE(NEWNOD) .LE. 0 ) GO TO 1200
  729. DEGREE (NEWNOD) = -DEGREE (NEWNOD)
  730. ACTIVE = ACTIVE + 1
  731. IF ( NLEVEL .LE. ACTIVE ) GO TO 5000
  732. IF ( ACTIVE .GT. NLEFT ) GO TO 6000
  733. LIST (ACTIVE) = NEWNOD
  734. 1200 CONTINUE
  735. FRONT = FRONT + 1
  736. C
  737. C ... IS QUEUE EMPTY?
  738. C -------------------
  739. C
  740. IF ( FRONT .LE. ACTIVE ) GO TO 1000
  741. C
  742. C ... YES, THE TREE IS BUILT. UNDO OUR MARKINGS.
  743. C
  744. DO 1300 J = 1, ACTIVE
  745. LISTJ = LIST(J)
  746. DEGREE (LISTJ) = -DEGREE (LISTJ)
  747. 1300 CONTINUE
  748. C
  749. RETURN
  750. C
  751. C ... INSUFFICIENT STORAGE ...
  752. C
  753. 5000 SPACE = 3 * ( (NLEFT+1-ACTIVE)*DEPTH / NLEFT + (NLEFT+1-ACTIVE) )
  754. ERROR = 110
  755. RETURN
  756. C
  757. 6000 ERROR = 12
  758. SPACE = -1
  759. RETURN
  760. C
  761. END
  762. SUBROUTINE GPSKCD (N, DEGREE, RSTART, CONNEC, STNODE, AVAIL,
  763. 1 ACTIVE, MXDPTH, LIST, DEPTH, WIDTH, MAXWID,
  764. 2 ERROR, SPACE)
  765. C
  766. C ==================================================================
  767. C BUILD THE LEVEL TREE ROOTED AT 'STNODE' IN THE SPACE PROVIDED IN
  768. C LIST. OVERFLOW CHECK NEEDED ONLY ON DEPTH OF TREE.
  769. C
  770. C BUILD THE LEVEL TREE TO COMPLETION ONLY IF THE WIDTH OF ALL
  771. C LEVELS IS SMALLER THAN 'MAXWID'. IF A WIDER LEVEL IS FOUND
  772. C TERMINATE THE CONSTRUCTION.
  773. C ==================================================================
  774. C
  775. IMPLICIT INTEGER(I-N)
  776. INTEGER N, RSTART(N), STNODE, AVAIL, ACTIVE, MXDPTH,
  777. 1 DEPTH, WIDTH, MAXWID, ERROR, SPACE
  778. C
  779. CIBM INTEGER *2 DEGREE(N), CONNEC(1), LIST(AVAIL)
  780. INTEGER DEGREE(N), CONNEC(1), LIST(AVAIL)
  781. C
  782. C ... PARAMETERS:
  783. C
  784. C INPUT ...
  785. C
  786. C N, DEGREE, RSTART, CONNEC -- DESCRIBE THE MATRIX STRUCTURE
  787. C
  788. C STNODE -- THE ROOT OF THE LEVEL TREE.
  789. C
  790. C AVAIL -- THE LENGTH OF THE WORKING SPACE AVAILABLE
  791. C
  792. C NLEFT -- THE NUMBER OF NODES YET TO BE NUMBERED
  793. C
  794. C ACTIVE -- THE NUMBER OF NODES IN THE COMPONENT
  795. C
  796. C MXDPTH -- MAXIMUM DEPTH OF LEVEL TREE POSSIBLE IN
  797. C ALLOTTED WORKING SPACE
  798. C
  799. C LIST -- THE WORKING SPACE.
  800. C
  801. C OUTPUT ...
  802. C
  803. C DEPTH -- THE DEPTH OF THE LEVEL TREE ROOTED AT STNODE.
  804. C
  805. C WIDTH -- THE WIDTH OF THE LEVEL TREE ROOTED AT STNODE.
  806. C
  807. C MAXWID -- LIMIT ON WIDTH OF THE TREE. TREE WILL NOT BE
  808. C USED IF WIDTH OF ANY LEVEL IS AS GREAT AS
  809. C MAXWID, SO CONSTRUCTION OF TREE NEED NOT
  810. C CONTINUE IF ANY LEVEL THAT WIDE IS FOUND.
  811. C ERROR -- ZERO UNLESS STORAGE WAS INSUFFICIENT.
  812. C
  813. C ------------------------------------------------------------------
  814. C
  815. INTEGER LSTART, NLEVEL, FRONT, J, NEWNOD, PTR, BACK,
  816. 1 SPTR, FPTR, LFRONT, LISTJ
  817. C
  818. C ... BUILD THE LEVEL TREE USING LIST AS A QUEUE AND LEAVING
  819. C THE NODES IN PLACE. THIS GENERATES THE NODES ORDERED BY LEVEL
  820. C PUT POINTERS TO THE BEGINNING OF EACH LEVEL, BUILDING FROM
  821. C THE BACK OF THE WORK AREA.
  822. C
  823. BACK = 1
  824. DEPTH = 0
  825. WIDTH = 0
  826. ERROR = 0
  827. LSTART = 1
  828. FRONT = 1
  829. LIST (BACK) = STNODE
  830. DEGREE (STNODE) = -DEGREE (STNODE)
  831. LIST (AVAIL) = 1
  832. NLEVEL = AVAIL
  833. C
  834. C ... REPEAT UNTIL QUEUE BECOMES EMPTY OR WE RUN OUT OF SPACE.
  835. C ------------------------------------------------------------
  836. C
  837. 1000 IF ( FRONT .LT. LSTART ) GO TO 1100
  838. C
  839. C ... FIRST NODE OF LEVEL. UPDATE POINTERS.
  840. C
  841. LSTART = BACK + 1
  842. WIDTH = MAX0 (WIDTH, LSTART - LIST(NLEVEL))
  843. IF ( WIDTH .GE. MAXWID ) GO TO 2000
  844. NLEVEL = NLEVEL - 1
  845. DEPTH = DEPTH + 1
  846. IF ( DEPTH .GT. MXDPTH ) GO TO 5000
  847. LIST (NLEVEL) = LSTART
  848. C
  849. C ... FIND ALL NEIGHBORS OF CURRENT NODE, ADD THEM TO QUEUE.
  850. C
  851. 1100 LFRONT = LIST (FRONT)
  852. SPTR = RSTART (LFRONT)
  853. FPTR = SPTR - DEGREE (LFRONT) - 1
  854. DO 1200 PTR = SPTR, FPTR
  855. NEWNOD = CONNEC (PTR)
  856. C
  857. C ... ADD TO QUEUE ONLY NODES NOT ALREADY IN QUEUE
  858. C
  859. IF ( DEGREE(NEWNOD) .LE. 0 ) GO TO 1200
  860. DEGREE (NEWNOD) = -DEGREE (NEWNOD)
  861. BACK = BACK + 1
  862. LIST (BACK) = NEWNOD
  863. 1200 CONTINUE
  864. FRONT = FRONT + 1
  865. C
  866. C ... IS QUEUE EMPTY?
  867. C -------------------
  868. C
  869. IF ( FRONT .LE. BACK ) GO TO 1000
  870. C
  871. C ... YES, THE TREE IS BUILT. UNDO OUR MARKINGS.
  872. C
  873. IF (BACK .NE. ACTIVE) GO TO 6000
  874. C
  875. 1300 DO 1400 J = 1, BACK
  876. LISTJ = LIST(J)
  877. DEGREE (LISTJ) = -DEGREE (LISTJ)
  878. 1400 CONTINUE
  879. C
  880. RETURN
  881. C
  882. C ... ABORT GENERATION OF TREE BECAUSE IT IS ALREADY TOO WIDE
  883. C
  884. 2000 WIDTH = N + 1
  885. DEPTH = 0
  886. GO TO 1300
  887. C
  888. C ... INSUFFICIENT STORAGE ...
  889. C
  890. 5000 SPACE = 3 * ( (ACTIVE+1-BACK)*DEPTH / ACTIVE + (ACTIVE+1-BACK) )
  891. ERROR = 111
  892. RETURN
  893. C
  894. 6000 ERROR = 13
  895. SPACE = -1
  896. RETURN
  897. C
  898. END
  899. SUBROUTINE GPSKCE (N, AVAIL, ACTIVE, DEPTH, WRKLEN,
  900. 1 LVLLST, LVLPTR, WORK, NXTNUM, TREE1, TREE2,
  901. 2 WIDTH1, WIDTH2, ONEIS1, ERROR, SPACE)
  902. C
  903. C ==================================================================
  904. C
  905. C TRANSITION BETWEEN ALGORITHM I AND ALGORITHM II OF
  906. C THE GIBBS-POOLE-STOCKMEYER PAPER.
  907. C
  908. C IN THIS IMPLEMENTATION ALGORITHM I REPRESENTS LEVEL TREES AS
  909. C LISTS OF NODES ORDERED BY LEVEL. ALGORITHM II APPEARS TO REQUIRE
  910. C LEVEL NUMBERS INDEXED BY NODE -- VECTORS FOR EFFICIENCY.
  911. C THIS SUBROUTINE CHANGES THE LEVEL TREE REPRESENTATION TO THAT
  912. C REQUIRED BY ALGORITHM II. NOTE THAT THE FIRST ALGORITHM CAN BE
  913. C CARRIED OUT WITH THE LEVEL NUMBER VECTOR FORMAT, PROBABLY REQURING
  914. C MORE COMPUTATION TIME, BUT PERHAPS LESS STORAGE.
  915. C
  916. C INPUT: TWO LEVEL TREES, AS LEVEL LISTS AND LEVEL POINTERS,
  917. C FOUND IN TWO OF THE THREE COLUMNS OF THE ARRAYS 'LVLLST'
  918. C AND 'LVLPTR'
  919. C
  920. C OUTPUT: TWO LEVEL TREES, AS VECTORS OF LEVEL NUMBERS,
  921. C ONE PACKED TO THE FRONT, ONE TO THE REAR OF THE WORKING
  922. C AREA 'WORK'. NOTE THAT 'WORK', 'LVLLST' AND 'LVLPTR'
  923. C SHARE COMMON LOCATIONS.
  924. C
  925. C ================================================================
  926. C
  927. C ... STRUCTURE OF WORKSPACE
  928. C
  929. C INPUT .. (OUTPUT FROM GPSKCB)
  930. C
  931. C --------------------------------------------------------------
  932. C : NUMBERED : TLIST1 PTR1 : TLIST2 PTR2 : TLIST3 PTR3 :
  933. C --------------------------------------------------------------
  934. C
  935. C OUTPUT .. (GOES TO COMBIN)
  936. C
  937. C --------------------------------------------------------------
  938. C : NUMBERED : TREE2 : ... : TREE1 :
  939. C --------------------------------------------------------------
  940. C
  941. C ==================================================================
  942. C
  943. IMPLICIT INTEGER(I-N)
  944. INTEGER N, AVAIL, ACTIVE, DEPTH, WRKLEN, NXTNUM,
  945. 1 WIDTH1, WIDTH2, TREE1, TREE2, ERROR, SPACE
  946. C
  947. CIBM INTEGER *2 LVLLST(AVAIL,3), LVLPTR(AVAIL,3), WORK(WRKLEN)
  948. INTEGER LVLLST(AVAIL,3), LVLPTR(AVAIL,3), WORK(WRKLEN)
  949. C
  950. LOGICAL ONEIS1
  951. C
  952. C ------------------------------------------------------------------
  953. C
  954. INTEGER I, BTREE, FTREE, FWIDTH, BWIDTH
  955. C
  956. C
  957. C ... CHECK THAT WE HAVE ENOUGH ROOM TO DO THE NECESSARY UNPACKING
  958. C
  959. IF (3*AVAIL .GT. WRKLEN) GO TO 6000
  960. IF (AVAIL .LT. N) GO TO 5100
  961. C
  962. C ... INPUT HAS THREE POSSIBLE CASES:
  963. C LVLLST(*,1) IS EMPTY
  964. C LVLLST(*,2) IS EMPTY
  965. C LVLLST(*,3) IS EMPTY
  966. C
  967. FTREE = TREE1
  968. BTREE = TREE2
  969. FWIDTH = WIDTH1
  970. BWIDTH = WIDTH2
  971. C
  972. TREE1 = WRKLEN - N + 1
  973. TREE2 = NXTNUM
  974. C
  975. IF ( (FTREE .EQ. 1) .OR. (BTREE .EQ. 1) ) GO TO 300
  976. C
  977. C ... CASE 1: 1ST SLOT IS EMPTY. UNPACK 3 INTO 1, 2 INTO 3
  978. C
  979. IF (FTREE .NE. 2) GO TO 100
  980. ONEIS1 = .TRUE.
  981. WIDTH2 = BWIDTH
  982. WIDTH1 = FWIDTH
  983. GO TO 200
  984. C
  985. 100 ONEIS1 = .FALSE.
  986. WIDTH1 = BWIDTH
  987. WIDTH2 = FWIDTH
  988. C
  989. 200 CALL GPSKCF (N, ACTIVE, DEPTH, LVLLST(1,3), LVLPTR(1,3),
  990. 1 WORK(TREE2), ONEIS1)
  991. C
  992. CALL GPSKCF (N, ACTIVE, DEPTH, LVLLST(1,2), LVLPTR(1,2),
  993. 1 WORK(TREE1), .NOT. ONEIS1)
  994. C
  995. GO TO 1000
  996. C
  997. C
  998. 300 IF ( (FTREE .EQ. 2) .OR. (BTREE .EQ. 2) ) GO TO 600
  999. C
  1000. C ... CASE 2: 2ND SLOT IS EMPTY. TO ENABLE COMPLETE
  1001. C REPACKING, MOVE 3 INTO 2, THEN FALL INTO NEXT CASE
  1002. C
  1003. DO 400 I = 1, ACTIVE
  1004. LVLLST(I,2) = LVLLST(I,3)
  1005. 400 CONTINUE
  1006. C
  1007. DO 500 I = 1, DEPTH
  1008. LVLPTR(I,2) = LVLPTR(I,3)
  1009. 500 CONTINUE
  1010. C
  1011. C ... CASE 3: SLOT 3 IS EMPTY. MOVE 1 INTO 3, THEN 2 INTO 1.
  1012. C
  1013. 600 IF (FTREE .EQ. 1) GO TO 700
  1014. ONEIS1 = .FALSE.
  1015. WIDTH1 = BWIDTH
  1016. WIDTH2 = FWIDTH
  1017. GO TO 800
  1018. C
  1019. 700 ONEIS1 = .TRUE.
  1020. WIDTH1 = FWIDTH
  1021. WIDTH2 = BWIDTH
  1022. C
  1023. 800 CALL GPSKCF (N, ACTIVE, DEPTH, LVLLST(1,1), LVLPTR(1,1),
  1024. 1 WORK(TREE1), .NOT. ONEIS1)
  1025. C
  1026. CALL GPSKCF (N, ACTIVE, DEPTH, LVLLST(1,2), LVLPTR(1,2),
  1027. 1 WORK(TREE2), ONEIS1)
  1028. 1000 RETURN
  1029. C
  1030. C ------------------------------------------------------------------
  1031. C
  1032. 5100 SPACE = 3 * (N - AVAIL)
  1033. ERROR = 120
  1034. RETURN
  1035. C
  1036. 6000 ERROR = 20
  1037. SPACE = -1
  1038. RETURN
  1039. C
  1040. END
  1041. SUBROUTINE GPSKCF (N, ACTIVE, DEPTH, LVLLST, LVLPTR, LVLNUM,
  1042. 1 REVERS)
  1043. C
  1044. C ==================================================================
  1045. C
  1046. C CONVERT LEVEL STRUCTURE REPRESENTATION FROM A LIST OF NODES
  1047. C GROUPED BY LEVEL TO A VECTOR GIVING LEVEL NUMBER FOR EACH NODE.
  1048. C
  1049. C LVLLST, LVLPTR -- LIST OF LISTS
  1050. C
  1051. C LVLNUM -- OUTPUT VECTOR OF LEVEL NUMBERS
  1052. C
  1053. C REVERS -- IF .TRUE., NUMBER LEVEL STRUCTURE FROM BACK END
  1054. C INSTEAD OF FROM FRONT
  1055. C
  1056. C ==================================================================
  1057. C
  1058. IMPLICIT INTEGER(I-N)
  1059. INTEGER N, ACTIVE, DEPTH
  1060. C
  1061. CIBM INTEGER *2 LVLLST(ACTIVE), LVLPTR(DEPTH), LVLNUM(N)
  1062. INTEGER LVLLST(ACTIVE), LVLPTR(DEPTH), LVLNUM(N)
  1063. LOGICAL REVERS
  1064. C
  1065. C ------------------------------------------------------------------
  1066. C
  1067. INTEGER I, LEVEL, LSTART, LEND, XLEVEL, PLSTRT, LVLLSI
  1068. C
  1069. IF (ACTIVE .EQ. N) GO TO 200
  1070. C
  1071. C ... IF NOT ALL NODES OF GRAPH ARE ACTIVE, MASK OUT THE
  1072. C NODES WHICH ARE NOT ACTIVE
  1073. C
  1074. DO 100 I = 1, N
  1075. LVLNUM(I) = 0
  1076. 100 CONTINUE
  1077. C
  1078. 200 DO 400 LEVEL = 1, DEPTH
  1079. XLEVEL = LEVEL
  1080. PLSTRT = DEPTH - LEVEL + 1
  1081. IF (REVERS) XLEVEL = PLSTRT
  1082. LSTART = LVLPTR (PLSTRT)
  1083. LEND = LVLPTR (PLSTRT - 1) - 1
  1084. C
  1085. DO 300 I = LSTART, LEND
  1086. LVLLSI = LVLLST(I)
  1087. LVLNUM (LVLLSI) = XLEVEL
  1088. 300 CONTINUE
  1089. 400 CONTINUE
  1090. C
  1091. RETURN
  1092. END
  1093. SUBROUTINE GPSKCG (N, DEGREE, RSTART, CONNEC, ACTIVE, WIDTH1,
  1094. 1 WIDTH2, TREE1, TREE2, WORK, WRKLEN, DEPTH,
  1095. 2 INC1, INC2, TOTAL, ONEIS1, REVRS1, ERROR,
  1096. 3 SPACE)
  1097. C
  1098. C ==================================================================
  1099. C
  1100. C COMBINE THE TWO ROOTED LEVEL TREES INTO A SINGLE LEVEL STRUCTURE
  1101. C WHICH MAY HAVE SMALLER WIDTH THAN EITHER OF THE TREES. THE NEW
  1102. C STRUCTURE IS NOT NECESSARILY A ROOTED STRUCTURE.
  1103. C
  1104. C PARAMETERS:
  1105. C
  1106. C N, DEGREE, RSTART, CONNEC -- GIVE THE DIMENSION AND STRUCTURE
  1107. C OF THE SPARSE SYMMETRIC MATRIX
  1108. C
  1109. C ACTIVE -- THE NUMBER OF NODES IN THIS CONNECTED COMPONENT OF
  1110. C THE MATRIX GRAPH
  1111. C
  1112. C TREE1 -- ON INPUT, ONE OF THE INPUT LEVEL TREES. ON
  1113. C OUTPUT, THE COMBINED LEVEL STRUCTURE
  1114. C
  1115. C TREE2 -- THE SECOND INPUT LEVEL TREE
  1116. C
  1117. C WIDTH1 -- THE MAXIMUM WIDTH OF A LEVEL IN TREE1
  1118. C
  1119. C WIDTH2 -- THE MAXIMUM WIDTH OF A LEVEL IN TREE2
  1120. C
  1121. C WORK -- A WORKING AREA OF LENGTH 'WRKLEN'
  1122. C
  1123. C INC1, -- VECTORS OF LENGTH 'DEPTH'
  1124. C INC2,
  1125. C TOTAL
  1126. C
  1127. C ONEIS1 -- INDICATES WHETHER TREE1 OR TREE2 REPRESENTS THE
  1128. C FORWARD TREE OR THE BACKWARDS TREE OF PHASE 1.
  1129. C USED TO MIMIC ARBITRARY TIE-BREAKING PROCEDURE OF
  1130. C ORIGINAL GIBBS-POOLE-STOCKMEYER CODE.
  1131. C
  1132. C REVRS1 -- OUTPUT PARAMETER INDICATING WHETHER A BACKWARDS
  1133. C ORDERING WAS USED FOR THE LARGEST COMPONENT OF
  1134. C THE REDUCED GRAPH
  1135. C
  1136. C ERROR -- NON-ZERO ONLY IF FAILURE OF SPACE ALLOCATION OR
  1137. C DATA STRUCTURE ERROR FOUND
  1138. C
  1139. C SPACE -- MINIMUM SPACE REQUIRED TO RERUN OR COMPLETE PHASE.
  1140. C
  1141. C ------------------------------------------------------------------
  1142. C
  1143. IMPLICIT INTEGER(I-N)
  1144. INTEGER N, RSTART(N), ACTIVE, WIDTH1, WIDTH2, WRKLEN, DEPTH,
  1145. 2 ERROR, SPACE
  1146. C
  1147. CIBM INTEGER *2 DEGREE(N), CONNEC(1), TREE1(N), TREE2(N),
  1148. INTEGER DEGREE(N), CONNEC(1), TREE1(N), TREE2(N),
  1149. 1 WORK(WRKLEN), INC1(DEPTH), INC2(DEPTH), TOTAL(DEPTH)
  1150. C
  1151. LOGICAL ONEIS1, REVRS1
  1152. C
  1153. C ==================================================================
  1154. C
  1155. C << REMOVE ALL NODES OF PSEUDO-DIAMETERS >>
  1156. C << FIND CONNECTED COMPONENTS OF REDUCED GRAPH >>
  1157. C << COMBINE LEVEL TREES, COMPONENT BY COMPONENT >>
  1158. C
  1159. C ==================================================================
  1160. C
  1161. C STRUCTURE OF WORKSPACE ...
  1162. C
  1163. C ------------------------------------------------------------------
  1164. C : NUMBERED : TREE2 : TOTAL : NODES : START : SIZE : INC1 : INC2 :
  1165. C ------------------------------------------------------------------
  1166. C
  1167. C --------
  1168. C TREE1 :
  1169. C --------
  1170. C
  1171. C NUMBERED IS THE SET OF NUMBERED NODES (PROBABLY EMPTY)
  1172. C
  1173. C TREE1 AND TREE1 ARE LEVEL TREES (LENGTH N)
  1174. C TOTAL, INC1 AND INC2 ARE VECTORS OF NODE COUNTS PER LEVEL
  1175. C (LENGTH 'DEPTH')
  1176. C NODES IS THE SET OF NODES IN THE REDUCED GRAPH (THE NODES
  1177. C NOT ON ANY SHORTEST PATH FROM ONE END OF THE
  1178. C PSEUDODIAMETER TO THE OTHER)
  1179. C START, SIZE ARE POINTERS INTO 'NODES', ONE OF EACH FOR
  1180. C EACH CONNECTED COMPONENT OF THE REDUCED GRAPH.
  1181. C THE SIZES OF NODES, START AND SIZE ARE NOT KNOWN APRIORI.
  1182. C
  1183. C ==================================================================
  1184. INTEGER I, SIZE, AVAIL, CSTOP, START, COMPON, TREE1I, PCSTRT,
  1185. 1 CSTART, MXINC1, MXINC2, COMPNS, MXCOMP, OFFDIA,
  1186. 2 CSIZE, PCSIZE, WORKI, TWORKI
  1187. C
  1188. C ------------------------------------------------------------------
  1189. C
  1190. C ... FIND ALL SHORTEST PATHS FROM START TO FINISH. REMOVE NODES ON
  1191. C THESE PATHS AND IN OTHER CONNECTED COMPONENTS OF FULL GRAPH
  1192. C FROM FURTHER CONSIDERATION. SIGN OF ENTRIES IN TREE1 IS USED
  1193. C AS A MASK.
  1194. C
  1195. OFFDIA = ACTIVE
  1196. C
  1197. DO 100 I = 1, DEPTH
  1198. TOTAL(I) = 0
  1199. 100 CONTINUE
  1200. C
  1201. DO 200 I = 1, N
  1202. TREE1I = TREE1 (I)
  1203. IF ((TREE1(I) .NE. TREE2(I)) .OR. (TREE1(I) .EQ. 0)) GO TO 200
  1204. TOTAL (TREE1I) = TOTAL (TREE1I) + 1
  1205. TREE1(I) = - TREE1(I)
  1206. OFFDIA = OFFDIA - 1
  1207. 200 CONTINUE
  1208. C
  1209. IF ( OFFDIA .EQ. 0 ) GO TO 1100
  1210. IF ( OFFDIA .LT. 0 ) GO TO 6000
  1211. C
  1212. C ... FIND CONNECTED COMPONENTS OF GRAPH INDUCED BY THE NODES NOT
  1213. C REMOVED. 'MXCOMP' IS THE LARGEST NUMBER OF COMPONENTS
  1214. C REPRESENTABLE IN THE WORKING SPACE AVAILABLE.
  1215. C
  1216. AVAIL = WRKLEN - OFFDIA
  1217. MXCOMP = AVAIL/2
  1218. START = OFFDIA + 1
  1219. SIZE = START + MXCOMP
  1220. C
  1221. IF (MXCOMP .LE. 0) GO TO 5100
  1222. C
  1223. CALL GPSKCH (N, DEGREE, RSTART, CONNEC, TREE1, OFFDIA, WORK,
  1224. 1 MXCOMP, WORK(START), WORK(SIZE), COMPNS, ERROR,
  1225. 2 SPACE)
  1226. IF ( ERROR .NE. 0 ) GO TO 5000
  1227. C
  1228. C ... RECORD SPACE ACTUALLY USED (NOT INCLUDING NUMBERED )
  1229. C
  1230. SPACE = 2*N + 3*(DEPTH) + 2*COMPNS + OFFDIA
  1231. C
  1232. C ... SORT THE COMPONENT START POINTERS INTO INCREASING ORDER
  1233. C OF SIZE OF COMPONENT
  1234. C
  1235. IF (COMPNS .GT. 1)
  1236. 1 CALL GPSKCN (COMPNS, WORK(SIZE), WORK(START), ERROR)
  1237. IF (ERROR .NE. 0) GO TO 6200
  1238. C
  1239. C ... FOR EACH COMPONENT IN TURN, CHOOSE TO USE THE ORDERING OF THE
  1240. C 'FORWARD' TREE1 OR OF THE 'BACKWARD' TREE2 TO NUMBER THE NODES
  1241. C IN THIS COMPONENT. THE NUMBERING IS CHOSEN TO MINIMIZE THE
  1242. C MAXIMUM INCREMENT TO ANY LEVEL.
  1243. C
  1244. DO 1000 COMPON = 1, COMPNS
  1245. PCSTRT = START + COMPON - 1
  1246. CSTART = WORK (PCSTRT)
  1247. PCSIZE = SIZE + COMPON - 1
  1248. CSIZE = WORK (PCSIZE)
  1249. CSTOP = CSTART + CSIZE - 1
  1250. IF ( ( CSIZE .LT. 0 ) .OR. ( CSIZE .GT. OFFDIA ) ) GO TO 6100
  1251. C
  1252. DO 300 I = 1, DEPTH
  1253. INC1(I) = 0
  1254. INC2(I) = 0
  1255. 300 CONTINUE
  1256. C
  1257. MXINC1 = 0
  1258. MXINC2 = 0
  1259. C
  1260. DO 400 I = CSTART, CSTOP
  1261. WORKI = WORK(I)
  1262. TWORKI = -TREE1 (WORKI)
  1263. INC1 (TWORKI) = INC1 (TWORKI) + 1
  1264. TWORKI = TREE2 (WORKI)
  1265. INC2 (TWORKI) = INC2 (TWORKI) + 1
  1266. 400 CONTINUE
  1267. C
  1268. C ... BAROQUE TESTS BELOW DUPLICATE THE GIBBS-POOLE-STOCKMEYER-
  1269. C CRANE PROGRAM, *** NOT *** THE PUBLISHED ALGORITHM.
  1270. C
  1271. DO 500 I = 1, DEPTH
  1272. IF ((INC1(I) .EQ. 0) .AND. (INC2(I) .EQ. 0)) GO TO 500
  1273. IF (MXINC1 .LT. TOTAL(I) + INC1(I))
  1274. 1 MXINC1 = TOTAL(I) + INC1(I)
  1275. IF (MXINC2 .LT. TOTAL(I) + INC2(I))
  1276. 1 MXINC2 = TOTAL(I) + INC2(I)
  1277. 500 CONTINUE
  1278. C
  1279. C ... USE ORDERING OF NARROWER TREE UNLESS IT INCREASES
  1280. C WIDTH MORE THAN WIDER TREE. IN CASE OF TIE, USE TREE 2!
  1281. C
  1282. IF ( (MXINC1 .GT. MXINC2) .OR.
  1283. 1 ( (MXINC1 .EQ. MXINC2) .AND. ( (WIDTH1 .GT. WIDTH2) .OR.
  1284. 2 ( (WIDTH1 .EQ. WIDTH2)
  1285. 3 .AND. ONEIS1) ) ) )
  1286. 4 GO TO 700
  1287. C
  1288. IF ( COMPON .EQ. 1 ) REVRS1 = .NOT. ONEIS1
  1289. C
  1290. DO 600 I = 1, DEPTH
  1291. TOTAL(I) = TOTAL(I) + INC1(I)
  1292. 600 CONTINUE
  1293. GO TO 1000
  1294. C
  1295. 700 IF ( COMPON .EQ. 1 ) REVRS1 = ONEIS1
  1296. DO 800 I = CSTART, CSTOP
  1297. WORKI = WORK(I)
  1298. TREE1 (WORKI) = - TREE2 (WORKI)
  1299. 800 CONTINUE
  1300. C
  1301. DO 900 I = 1, DEPTH
  1302. TOTAL(I) = TOTAL(I) + INC2(I)
  1303. 900 CONTINUE
  1304. C
  1305. 1000 CONTINUE
  1306. GO TO 2000
  1307. C
  1308. C ... DEFAULT WHEN THE REDUCED GRAPH IS EMPTY
  1309. C
  1310. 1100 REVRS1 = .TRUE.
  1311. SPACE = 2*N
  1312. C
  1313. 2000 RETURN
  1314. C
  1315. C ------------------------------------------------------------------
  1316. C
  1317. C ERROR FOUND ...
  1318. C
  1319. 5000 SPACE = -1
  1320. GO TO 2000
  1321. C
  1322. 5100 SPACE = 2 - AVAIL
  1323. ERROR = 131
  1324. GO TO 2000
  1325. C
  1326. 6000 ERROR = 30
  1327. GO TO 5000
  1328. C
  1329. 6100 ERROR = 31
  1330. GO TO 5000
  1331. C
  1332. 6200 ERROR = 32
  1333. GO TO 5000
  1334. C
  1335. END
  1336. SUBROUTINE GPSKCH (N, DEGREE, RSTART, CONNEC, STATUS, NREDUC,
  1337. 1 WORK, MXCOMP, START, SIZE, COMPNS, ERROR,
  1338. 2 SPACE)
  1339. C
  1340. C ==================================================================
  1341. C
  1342. C FIND THE CONNECTED COMPONENTS OF THE GRAPH INDUCED BY THE SET
  1343. C OF NODES WITH POSITIVE 'STATUS'. WE SHALL BUILD THE LIST OF
  1344. C CONNECTED COMPONENTS IN 'WORK', WITH A LIST OF POINTERS
  1345. C TO THE BEGINNING NODES OF COMPONENTS LOCATED IN 'START'
  1346. C
  1347. C
  1348. IMPLICIT INTEGER(I-N)
  1349. INTEGER N, RSTART(N), NREDUC, MXCOMP, COMPNS, ERROR, SPACE
  1350. C
  1351. CIBM INTEGER *2 DEGREE(N), CONNEC(1), STATUS(N), WORK(NREDUC),
  1352. INTEGER DEGREE(N), CONNEC(1), STATUS(N), WORK(NREDUC),
  1353. 1 START(MXCOMP), SIZE(MXCOMP)
  1354. C
  1355. C
  1356. C PARAMETERS ...
  1357. C
  1358. C N -- DIMENSION OF THE ORIGINAL MATRIX
  1359. C DEGREE, RSTART, CONNEC -- THE STRUCTURE OF THE ORIGINAL MATRIX
  1360. C
  1361. C STATUS -- DERIVED FROM A LEVEL TREE. POSITIVE ENTRIES INDICATE
  1362. C ACTIVE NODES. NODES WITH STATUS <= 0 ARE IGNORED.
  1363. C
  1364. C NREDUC -- THE NUMBER OF ACTIVE NODES
  1365. C
  1366. C WORK -- WORK SPACE, USED AS A QUEUE TO BUILD CONNECTED
  1367. C COMPONENTS IN PLACE.
  1368. C
  1369. C MXCOMP -- MAXIMUM NUMBER OF COMPONENTS ALLOWED BY CURRENT
  1370. C SPACE ALLOCATION. MUST NOT BE VIOLATED.
  1371. C
  1372. C START -- POINTER TO BEGINNING OF I-TH CONNECTED COMPONENT
  1373. C
  1374. C SIZE -- SIZE OF EACH COMPONENT
  1375. C
  1376. C COMPNS -- NUMBER OF COMPONENTS ACTUALLY FOUND
  1377. C
  1378. C ERROR -- SHOULD BE ZERO ON RETURN UNLESS WE HAVE TOO LITTLE
  1379. C SPACE OR WE ENCOUNTER AN ERROR IN THE DATA STRUCTURE
  1380. C
  1381. C SPACE -- MAXIMUM AMOUNT OF WORKSPACE USED / NEEDED
  1382. C
  1383. C ==================================================================
  1384. C
  1385. INTEGER I, J, FREE, JPTR, NODE, JNODE, FRONT, CDGREE, ROOT
  1386. C
  1387. C ------------------------------------------------------------------
  1388. C
  1389. C
  1390. C REPEAT
  1391. C << FIND AN UNASSIGNED NODE AND START A NEW COMPONENT >>
  1392. C REPEAT
  1393. C << ADD ALL NEW NEIGHBORS OF FRONT NODE TO QUEUE, >>
  1394. C << REMOVE FRONT NODE. >>
  1395. C UNTIL <<QUEUE EMPTY>>
  1396. C UNTIL << ALL NODES ASSIGNED >>
  1397. C
  1398. FREE = 1
  1399. COMPNS = 0
  1400. ROOT = 1
  1401. C
  1402. C ... START OF OUTER REPEAT LOOP
  1403. C
  1404. C ... FIND AN UNASSIGNED NODE
  1405. C
  1406. 100 DO 200 I = ROOT, N
  1407. IF (STATUS(I) .LE. 0) GO TO 200
  1408. NODE = I
  1409. GO TO 300
  1410. 200 CONTINUE
  1411. GO TO 6100
  1412. C
  1413. C ... START NEW COMPONENT
  1414. C
  1415. 300 COMPNS = COMPNS + 1
  1416. ROOT = NODE + 1
  1417. IF (COMPNS .GT. MXCOMP) GO TO 5000
  1418. START (COMPNS) = FREE
  1419. WORK (FREE) = NODE
  1420. STATUS (NODE) = -STATUS (NODE)
  1421. FRONT = FREE
  1422. FREE = FREE + 1
  1423. C
  1424. C ... INNER REPEAT UNTIL QUEUE BECOMES EMPTY
  1425. C
  1426. 400 NODE = WORK (FRONT)
  1427. FRONT = FRONT + 1
  1428. C
  1429. JPTR = RSTART (NODE)
  1430. CDGREE = DEGREE (NODE)
  1431. DO 500 J = 1, CDGREE
  1432. JNODE = CONNEC (JPTR)
  1433. JPTR = JPTR + 1
  1434. IF (STATUS(JNODE) .LT. 0) GO TO 500
  1435. IF (STATUS(JNODE) .EQ. 0) GO TO 6000
  1436. STATUS (JNODE) = -STATUS (JNODE)
  1437. WORK (FREE) = JNODE
  1438. FREE = FREE + 1
  1439. 500 CONTINUE
  1440. C
  1441. IF (FRONT .LT. FREE) GO TO 400
  1442. C
  1443. C ... END OF INNER REPEAT. COMPUTE SIZE OF COMPONENT AND
  1444. C SEE IF THERE ARE MORE NODES TO BE ASSIGNED
  1445. C
  1446. SIZE (COMPNS) = FREE - START (COMPNS)
  1447. IF (FREE .LE. NREDUC) GO TO 100
  1448. C
  1449. IF (FREE .NE. NREDUC+1) GO TO 6200
  1450. RETURN
  1451. C
  1452. C ------------------------------------------------------------------
  1453. C
  1454. 5000 SPACE = NREDUC - FREE + 1
  1455. ERROR = 130
  1456. RETURN
  1457. C
  1458. 6000 ERROR = 33
  1459. SPACE = -1
  1460. RETURN
  1461. C
  1462. 6100 ERROR = 34
  1463. SPACE = -1
  1464. RETURN
  1465. C
  1466. 6200 ERROR = 35
  1467. SPACE = -1
  1468. RETURN
  1469. END
  1470. SUBROUTINE GPSKCI (N, ACTIVE, DEPTH, LSTRUC, LVLLST, LVLPTR,
  1471. 1 LTOTAL, ERROR, SPACE)
  1472. C
  1473. C ==================================================================
  1474. C
  1475. C TRANSITIONAL SUBROUTINE, ALGORITHM II TO IIIA OR IIIB.
  1476. C
  1477. C CONVERT LEVEL STRUCTURE GIVEN AS VECTOR OF LEVEL NUMBERS FOR NODES
  1478. C TO STRUCTURE AS LIST OF NODES BY LEVEL
  1479. C
  1480. C N, ACTIVE, DEPTH -- PROBLEM SIZES
  1481. C LSTRUC -- INPUT LEVEL STRUCTURE
  1482. C LVLLST, LVLPTR -- OUTPUT LEVEL STRUCTURE
  1483. C LTOTAL -- NUMBER OF NODES AT EACH LEVEL (PRECOMPUTED)
  1484. C
  1485. IMPLICIT INTEGER(I-N)
  1486. INTEGER N, ACTIVE, DEPTH, ERROR, SPACE
  1487. C
  1488. CIBM INTEGER *2 LSTRUC(N), LVLLST(ACTIVE), LVLPTR(1), LTOTAL(DEPTH)
  1489. INTEGER LSTRUC(N), LVLLST(ACTIVE), LVLPTR(*), LTOTAL(DEPTH)
  1490. C
  1491. C ===============================================================
  1492. C
  1493. C STRUCTURE OF WORKSPACE ..
  1494. C
  1495. C INPUT (FROM COMBIN) ..
  1496. C
  1497. C ------------------------------------------------------------------
  1498. C : NUMBERED : ..(N).. : TOTAL : ... : TREE :
  1499. C ------------------------------------------------------------------
  1500. C
  1501. C OUTPUT (TO GPSKCJ OR GPSKCK) ..
  1502. C
  1503. C ------------------------------------------------------------------
  1504. C : NUMBERED : ... : TLIST : TPTR : TREE :
  1505. C ------------------------------------------------------------------
  1506. C
  1507. C HERE, NUMBERED IS THE SET OF NODES IN NUMBERED COMPONENTS
  1508. C TOTAL IS A VECTOR OF LENGTH 'DEPTH' GIVING THE NUMBER
  1509. C OF NODES IN EACH LEVEL OF THE 'TREE'.
  1510. C TLIST, TPTR ARE LISTS OF NODES OF THE TREE, ARRANGED
  1511. C BY LEVEL. TLIST IS OF LENGTH 'ACTIVE', TPTR 'DEPTH+1'.
  1512. C
  1513. C =================================================================
  1514. C
  1515. INTEGER I, ACOUNT, START, LEVEL, PLEVEL
  1516. C
  1517. C ... ESTABLISH STARTING AND ENDING POINTERS FOR EACH LEVEL
  1518. C
  1519. START = 1
  1520. DO 100 I = 1, DEPTH
  1521. LVLPTR(I) = START
  1522. START = START + LTOTAL(I)
  1523. LTOTAL(I) = START
  1524. 100 CONTINUE
  1525. LVLPTR(DEPTH+1) = START
  1526. C
  1527. ACOUNT = 0
  1528. DO 300 I = 1, N
  1529. IF (LSTRUC(I)) 200, 300, 6000
  1530. 200 LEVEL = -LSTRUC(I)
  1531. LSTRUC(I) = LEVEL
  1532. PLEVEL = LVLPTR (LEVEL)
  1533. LVLLST (PLEVEL) = I
  1534. LVLPTR (LEVEL) = LVLPTR (LEVEL) + 1
  1535. ACOUNT = ACOUNT + 1
  1536. IF (LVLPTR (LEVEL) .GT. LTOTAL (LEVEL)) GO TO 6100
  1537. 300 CONTINUE
  1538. C
  1539. C ... RESET STARTING POINTERS
  1540. C
  1541. LVLPTR(1) = 1
  1542. DO 400 I = 1, DEPTH
  1543. LVLPTR(I+1) = LTOTAL(I)
  1544. 400 CONTINUE
  1545. C
  1546. RETURN
  1547. C
  1548. C ------------------------------------------------------------------
  1549. C
  1550. 6000 ERROR = 40
  1551. GO TO 6200
  1552. C
  1553. 6100 ERROR = 41
  1554. C
  1555. 6200 SPACE = -1
  1556. RETURN
  1557. C
  1558. END
  1559. SUBROUTINE GPSKCJ (N, DEGREE, RSTART, CONNEC,
  1560. 1 NCOMPN, INVNUM, SNODE1, SNODE2, REVRS1,
  1561. 2 DEPTH, LVLLST, LVLPTR, LVLNUM, ERROR,
  1562. 3 SPACE)
  1563. C
  1564. C ==================================================================
  1565. C
  1566. C NUMBER THE NODES IN A GENERALIZED LEVEL STRUCTURE ACCORDING
  1567. C TO A GENERALIZATION OF THE CUTHILL MCKEE STRATEGY.
  1568. C
  1569. C N -- DIMENSION OF ORIGINAL PROBLEM
  1570. C DEGREE, RSTART, CONNEC -- GIVE STRUCTURE OF SPARSE AND
  1571. C SYMMETRIC MATRIX
  1572. C
  1573. C NCOMPN -- NUMBER OF NODES IN THIS COMPONENT OF MATRIX GRAPH
  1574. C
  1575. C INVNUM -- WILL BECOME A LIST OF THE ORIGINAL NODES IN THE ORDER
  1576. C WHICH REDUCES THE BANDWIDTH OF THE MATRIX.
  1577. C
  1578. C NXTNUM -- THE NEXT INDEX TO BE ASSIGNED (1 FOR FIRST COMPONENT)
  1579. C
  1580. C REVRS1 -- IF .TRUE., FIRST COMPONENT OF REDUCED GRAPH WAS NUMBERED
  1581. C BACKWARDS.
  1582. C
  1583. C LVLLST -- LIST OF NODES IN LEVEL TREE ORDERED BY LEVEL.
  1584. C
  1585. C LVLPTR -- POSITION OF INITIAL NODE IN EACH LEVEL OF LVLLST.
  1586. C
  1587. C LVLNUM -- LEVEL NUMBER OF EACH NODE IN COMPONENT
  1588. C
  1589. C
  1590. IMPLICIT INTEGER(I-N)
  1591. INTEGER N, RSTART(N), NCOMPN, SNODE1, SNODE2, DEPTH,
  1592. 1 ERROR, SPACE
  1593. C
  1594. CIBM INTEGER *2 DEGREE(N), CONNEC(1), INVNUM(NCOMPN),
  1595. INTEGER DEGREE(N), CONNEC(1), INVNUM(NCOMPN),
  1596. 1 LVLLST(NCOMPN), LVLPTR(DEPTH), LVLNUM(N)
  1597. C
  1598. LOGICAL REVRS1
  1599. C
  1600. C
  1601. C ==================================================================
  1602. C
  1603. C NUMBERING REQUIRES TWO QUEUES, WHICH CAN BE BUILD IN PLACE
  1604. C IN INVNUM.
  1605. C
  1606. C
  1607. C ==================================================================
  1608. C A L G O R I T H M S T R U C T U R E
  1609. C ==================================================================
  1610. C
  1611. C << SET QUEUE1 TO BE THE SET CONTAINING ONLY THE START NODE. >>
  1612. C
  1613. C FOR LEVEL = 1 TO DEPTH DO
  1614. C
  1615. C BEGIN
  1616. C LOOP
  1617. C
  1618. C REPEAT
  1619. C BEGIN
  1620. C << CNODE <- FRONT OF QUEUE1 >>
  1621. C << ADD UNNUMBERED NEIGHBORS OF CNODE TO THE BACK >>
  1622. C << OF QUEUE1 OR QUEUE2 (USE QUEUE1 IF NEIGHBOR >>
  1623. C << AT SAME LEVEL, QUEUE2 IF AT NEXT LEVEL). SORT >>
  1624. C << THE NEWLY QUEUED NODES INTO INCREASING ORDER OF >>
  1625. C << DEGREE. NUMBER CNODE, DELETE IT FROM QUEUE1. >>
  1626. C END
  1627. C UNTIL
  1628. C << QUEUE1 IS EMPTY >>
  1629. C
  1630. C EXIT IF << ALL NODES AT THIS LEVEL NUMBERED >>
  1631. C
  1632. C BEGIN
  1633. C << FIND THE UNNUMBERED NODE OF MINIMAL DEGREE AT THIS >>
  1634. C << LEVEL, RESTART QUEUE1 WITH THIS NODE. >>
  1635. C END
  1636. C
  1637. C END << LOOP LOOP >>
  1638. C
  1639. C << PROMOTE QUEUE2 TO BE INITIAL QUEUE1 FOR NEXT ITERATION >>
  1640. C << OF FOR LOOP. >>
  1641. C
  1642. C END <<FOR LOOP>>
  1643. C
  1644. C ==================================================================
  1645. C
  1646. C STRUCTURE OF WORKSPACE ..
  1647. C
  1648. C --------------------------------------------------------------
  1649. C : NUMBERED : QUEUE1 : QUEUE2 : ... : TLIST : TPTR : TREE :
  1650. C --------------------------------------------------------------
  1651. C
  1652. C ON COMPLETION, WE HAVE ONLY A NEW, LONGER NUMBERED SET.
  1653. C
  1654. C ==================================================================
  1655. INTEGER I, BQ1, BQ2, FQ1, INC, CPTR, CNODE,
  1656. 1 INODE, LEVEL, NLEFT, LSTART, LWIDTH, QUEUE1,
  1657. 2 QUEUE2, CDGREE, XLEVEL, STNODE, ILEVEL, SQ1, SQ2,
  1658. 3 NSORT, LOWDG, BPTR, LVLLSC, LVLLSB, INVNMI
  1659. C
  1660. LOGICAL FORWRD, RLEVEL
  1661. C
  1662. C ------------------------------------------------------------------
  1663. C
  1664. C ... GIBBS-POOLE-STOCKMEYER HEURISTIC CHOICE OF ORDER
  1665. C
  1666. IF (DEGREE(SNODE1) .GT. DEGREE(SNODE2)) GO TO 10
  1667. FORWRD = REVRS1
  1668. STNODE = SNODE1
  1669. GO TO 20
  1670. C
  1671. 10 FORWRD = .NOT. REVRS1
  1672. STNODE = SNODE2
  1673. C
  1674. C ... SET UP INITIAL QUEUES AT FRONT OF 'INVNUM' FOR FORWRD ORDER,
  1675. C AT BACK FOR REVERSED ORDER.
  1676. C
  1677. 20 IF (FORWRD) GO TO 100
  1678. INC = -1
  1679. QUEUE1 = NCOMPN
  1680. GO TO 200
  1681. C
  1682. 100 INC = +1
  1683. QUEUE1 = 1
  1684. C
  1685. 200 INVNUM (QUEUE1) = STNODE
  1686. RLEVEL = (LVLNUM(STNODE) .EQ. DEPTH)
  1687. LVLNUM (STNODE) = 0
  1688. FQ1 = QUEUE1
  1689. BQ1 = QUEUE1 + INC
  1690. C
  1691. C -------------------------------
  1692. C NUMBER NODES LEVEL BY LEVEL ...
  1693. C -------------------------------
  1694. C
  1695. DO 3000 XLEVEL = 1, DEPTH
  1696. LEVEL = XLEVEL
  1697. IF (RLEVEL) LEVEL = DEPTH - XLEVEL + 1
  1698. C
  1699. LSTART = LVLPTR (LEVEL)
  1700. LWIDTH = LVLPTR (LEVEL+1) - LSTART
  1701. NLEFT = LWIDTH
  1702. QUEUE2 = QUEUE1 + INC*LWIDTH
  1703. BQ2 = QUEUE2
  1704. C
  1705. C ==============================================================
  1706. C ... 'LOOP' CONSTRUCT BEGINS AT STATEMENT 1000
  1707. C THE INNER 'REPEAT' WILL BE DONE AS MANY TIMES AS
  1708. C IS NECESSARY TO NUMBER ALL THE NODES AT THIS LEVEL.
  1709. C ==============================================================
  1710. C
  1711. 1000 CONTINUE
  1712. C
  1713. C ==========================================================
  1714. C ... REPEAT ... UNTIL QUEUE1 BECOMES EMPTY
  1715. C TAKE NODE FROM FRONT OF QUEUE1, FIND EACH OF ITS
  1716. C NEIGHBORS WHICH HAVE NOT YET BEEN NUMBERED, AND
  1717. C ADD THE NEIGHBORS TO QUEUE1 OR QUEUE2 ACCORDING TO
  1718. C THEIR LEVELS.
  1719. C ==========================================================
  1720. C
  1721. 1100 CNODE = INVNUM (FQ1)
  1722. FQ1 = FQ1 + INC
  1723. SQ1 = BQ1
  1724. SQ2 = BQ2
  1725. NLEFT = NLEFT - 1
  1726. C
  1727. CPTR = RSTART (CNODE)
  1728. CDGREE = DEGREE (CNODE)
  1729. DO 1300 I = 1, CDGREE
  1730. INODE = CONNEC (CPTR)
  1731. CPTR = CPTR + 1
  1732. ILEVEL = LVLNUM (INODE)
  1733. IF (ILEVEL .EQ. 0) GO TO 1300
  1734. LVLNUM (INODE) = 0
  1735. IF ( ILEVEL .EQ. LEVEL ) GO TO 1200
  1736. C
  1737. IF (IABS(LEVEL-ILEVEL) .NE. 1) GO TO 6400
  1738. INVNUM (BQ2) = INODE
  1739. BQ2 = BQ2 + INC
  1740. GO TO 1300
  1741. C
  1742. 1200 INVNUM (BQ1) = INODE
  1743. BQ1 = BQ1 + INC
  1744. 1300 CONTINUE
  1745. C
  1746. C ==================================================
  1747. C ... SORT THE NODES JUST ADDED TO QUEUE1 AND QUEUE2
  1748. C SEPARATELY INTO INCREASING ORDER OF DEGREE.
  1749. C ==================================================
  1750. C
  1751. IF (IABS (BQ1 - SQ1) .LE. 1) GO TO 1500
  1752. NSORT = IABS (BQ1 - SQ1)
  1753. IF (FORWRD) GO TO 1400
  1754. CALL GPSKCP (NSORT, INVNUM(BQ1+1), N, DEGREE,
  1755. 1 ERROR)
  1756. IF (ERROR .NE. 0) GO TO 6600
  1757. GO TO 1500
  1758. C
  1759. 1400 CALL GPSKCQ (NSORT, INVNUM(SQ1), N, DEGREE,
  1760. 1 ERROR)
  1761. IF (ERROR .NE. 0) GO TO 6600
  1762. C
  1763. 1500 IF (IABS (BQ2 - SQ2) .LE. 1) GO TO 1700
  1764. NSORT = IABS (BQ2 - SQ2)
  1765. IF (FORWRD) GO TO 1600
  1766. CALL GPSKCP (NSORT, INVNUM(BQ2+1), N, DEGREE,
  1767. 1 ERROR)
  1768. IF (ERROR .NE. 0) GO TO 6600
  1769. GO TO 1700
  1770. C
  1771. 1600 CALL GPSKCQ (NSORT, INVNUM(SQ2), N, DEGREE,
  1772. 1 ERROR)
  1773. IF (ERROR .NE. 0) GO TO 6600
  1774. C
  1775. C ... END OF REPEAT LOOP
  1776. C
  1777. 1700 IF (FQ1 .NE. BQ1) GO TO 1100
  1778. C
  1779. C ==============================================================
  1780. C ... QUEUE1 IS NOW EMPTY ...
  1781. C IF THERE ARE ANY UNNUMBERED NODES LEFT AT THIS LEVEL,
  1782. C FIND THE ONE OF MINIMAL DEGREE AND RETURN TO THE
  1783. C REPEAT LOOP ABOVE.
  1784. C ==============================================================
  1785. C
  1786. 2000 IF ((BQ1 .EQ. QUEUE2) .AND. (NLEFT .EQ. 0)) GO TO 2900
  1787. C
  1788. IF ((NLEFT .LE. 0) .OR. (NLEFT .NE. INC * (QUEUE2 - BQ1)))
  1789. 1 GO TO 6200
  1790. C
  1791. LOWDG = N + 1
  1792. BPTR = N + 1
  1793. CPTR = LSTART - 1
  1794. DO 2800 I = 1, NLEFT
  1795. 2600 CPTR = CPTR + 1
  1796. LVLLSC = LVLLST (CPTR)
  1797. IF (LVLNUM (LVLLSC) .EQ. LEVEL) GO TO 2700
  1798. IF (LVLNUM (LVLLSC) .NE. 0) GO TO 6300
  1799. GO TO 2600
  1800. C
  1801. 2700 IF (DEGREE(LVLLSC) .GE. LOWDG) GO TO 2800
  1802. LOWDG = DEGREE (LVLLSC)
  1803. BPTR = CPTR
  1804. C
  1805. 2800 CONTINUE
  1806. C
  1807. C ... MINIMAL DEGREE UNNUMBERED NODE FOUND ...
  1808. C
  1809. IF (BPTR .GT. N) GO TO 6500
  1810. LVLLSB = LVLLST (BPTR)
  1811. INVNUM (BQ1) = LVLLSB
  1812. LVLNUM (LVLLSB) = 0
  1813. BQ1 = BQ1 + INC
  1814. GO TO 1000
  1815. C
  1816. C =============================================
  1817. C ... ADVANCE QUEUE POINTERS TO MAKE QUEUE2 THE
  1818. C NEW QUEUE1 FOR THE NEXT ITERATION.
  1819. C =============================================
  1820. C
  1821. 2900 QUEUE1 = QUEUE2
  1822. FQ1 = QUEUE1
  1823. BQ1 = BQ2
  1824. IF ((BQ1 .EQ. FQ1) .AND. (XLEVEL .LT. DEPTH)) GO TO 6100
  1825. C
  1826. 3000 CONTINUE
  1827. C
  1828. C ... CHANGE SIGN OF DEGREE TO MARK THESE NODES AS 'NUMBERED'
  1829. C
  1830. DO 3100 I = 1, NCOMPN
  1831. INVNMI = INVNUM(I)
  1832. DEGREE (INVNMI) = -DEGREE (INVNMI)
  1833. 3100 CONTINUE
  1834. C
  1835. RETURN
  1836. C
  1837. C ------------------------------------------------------------------
  1838. C
  1839. 6000 SPACE = -1
  1840. RETURN
  1841. C
  1842. 6100 ERROR = 51
  1843. GO TO 6000
  1844. C
  1845. 6200 ERROR = 52
  1846. GO TO 6000
  1847. C
  1848. 6300 ERROR = 53
  1849. GO TO 6000
  1850. C
  1851. 6400 ERROR = 54
  1852. GO TO 6000
  1853. C
  1854. 6500 ERROR = 55
  1855. GO TO 6000
  1856. C
  1857. 6600 ERROR = 56
  1858. GO TO 6000
  1859. C
  1860. END
  1861. SUBROUTINE GPSKCK (N, DEGREE, RSTART, CONNEC, WRKLEN, NXTNUM,
  1862. 1 WORK, NCOMPN, DEPTH, LVLLST, LVLPTR, LVLNUM,
  1863. 2 ERROR, SPACE)
  1864. C
  1865. IMPLICIT INTEGER(I-N)
  1866. INTEGER N, RSTART(N), WRKLEN, NXTNUM, NCOMPN, DEPTH, ERROR,
  1867. 1 SPACE
  1868. C
  1869. CIBM INTEGER *2 DEGREE(N), CONNEC(1), WORK(WRKLEN), LVLLST(N),
  1870. INTEGER DEGREE(N), CONNEC(1), WORK(WRKLEN), LVLLST(N),
  1871. 1 LVLPTR(DEPTH), LVLNUM(N)
  1872. C
  1873. C ==================================================================
  1874. C
  1875. C NUMBER NODES IN A GENERALIZED LEVEL STRUCTURE ACCORDING TO
  1876. C A GENERALIZATION OF THE KING ALGORITHM, WHICH REDUCES
  1877. C THE PROFILE OF THE SPARSE SYMMETRIC MATRIX.
  1878. C
  1879. C ---------------------
  1880. C
  1881. C CODE USES A PRIORITY QUEUE TO CHOOSE THE NEXT NODE TO BE NUMBERED
  1882. C THE PRIORITY QUEUE IS REPRESENTED BY A SIMPLE LINEAR-LINKED LIST
  1883. C TO SAVE SPACE. THIS WILL REQUIRE MORE SEARCHING THAN A FULLY
  1884. C LINKED REPRESENTATION, BUT THE DATA MANIPULATION IS SIMPLER.
  1885. C
  1886. C -------------------
  1887. C
  1888. C << ESTABLISH PRIORITY QUEUE 'ACTIVE' FOR LEVEL 1 NODES >>
  1889. C
  1890. C FOR I = 1 TO DEPTH DO
  1891. C << SET QUEUE 'QUEUED' TO BE EMPTY, LIST 'NEXT' TO BE >>
  1892. C << SET OF NODES AT NEXT LEVEL. >>
  1893. C
  1894. C FOR J = 1 TO 'NODES AT THIS LEVEL' DO
  1895. C << FIND FIRST NODE IN ACTIVE WITH MINIMAL CONNECTIONS >>
  1896. C << TO 'NEXT'. NUMBER THIS NODE AND REMOVE HIM FROM >>
  1897. C << 'ACTIVE'. FOR EACH NODE IN 'NEXT' WHICH CONNECTED >>
  1898. C << TO THIS NODE, MOVE IT TO 'QUEUED' AND REMOVE IT >>
  1899. C << FROM 'NEXT'. >>
  1900. C
  1901. C << SET NEW QUEUE 'ACTIVE' TO BE 'QUEUED' FOLLOWED BY ANY >>
  1902. C << NODES STILL IN 'NEXT'. >>
  1903. C
  1904. C ==================================================================
  1905. C
  1906. C DATA STRUCTURE ASSUMPTIONS:
  1907. C THE FIRST 'NXTNUM-1' ELEMENTS OF WORK ARE ALREADY IN USE.
  1908. C THE LEVEL STRUCTURE 'LVLLST' IS CONTIGUOUS WITH WORK, THAT IS,
  1909. C IT RESIDES IN ELEMENTS WRKLEN+1, ... OF WORK. 'LVLPTR' AND
  1910. C 'LVLNUM' ARE ALSO EMBEDDED IN WORK, BEHIND 'LVLLST'. THE
  1911. C THREE VECTORS ARE PASSED SEPARATELY TO CLARIFY THE INDEXING,
  1912. C BUT THE QUEUES DEVELOPED WILL BE ALLOWED TO OVERRUN 'LVLLST'
  1913. C AS NEEDED.
  1914. C
  1915. C ... BUILD THE FIRST 'ACTIVE' QUEUE STARTING W1 LOCATIONS FROM
  1916. C THE FRONT OF THE CURRENT WORKING AREA (W1 IS THE WIDTH OF THE
  1917. C FIRST LEVEL). BUILD THE FIRST 'QUEUED' QUEUE STARTING FROM
  1918. C THE BACK OF WORK SPACE. THE LIST 'NEXT' WILL BE REALIZED
  1919. C LVLNUM(I) > 0 <== LEVEL NUMBER OF NODE. 'NEXT' IS
  1920. C SET WITH LVLNUM(I) = LEVEL+1
  1921. C LVLNUM(I) = 0 <== I-TH NODE IS IN 'QUEUED' OR IS
  1922. C NOT IN THIS COMPONENT OF GRAPH,
  1923. C OR HAS JUST BEEN NUMBERED.
  1924. C LVLNUM(I) < 0 <== I-TH NODE IS IN 'ACTIVE' AND IS
  1925. C CONNECTED TO -LVLNUM(I) NODES IN
  1926. C 'NEXT'.
  1927. C
  1928. C ==================================================================
  1929. C
  1930. C STRUCTURE OF WORKSPACE ..
  1931. C
  1932. C --------------------------------------------------------------
  1933. C : NUMBERED : DONE : ACTIVE : ALEVEL : ... : QUEUED : LVLLST :
  1934. C --------------------------------------------------------------
  1935. C
  1936. C -------------------
  1937. C LVLPTR : LVLNUM :
  1938. C -------------------
  1939. C
  1940. C IN THE ABOVE,
  1941. C NUMBERED IS THE SET OF NODES ALREADY NUMBERED FROM
  1942. C PREVIOUS COMPONENTS AND EARLIER LEVELS OF THIS COMPONENT.
  1943. C DONE, ACTIVE, ALEVEL ARE VECTORS OF LENGTH THE WIDTH OF
  1944. C THE CURRENT LEVEL. ACTIVE IS A SET OF INDICES INTO
  1945. C ALEVEL. AS THE NODES IN ALEVEL ARE NUMBERED, THEY
  1946. C ARE PLACED INTO 'DONE'.
  1947. C QUEUED IS A QUEUE OF NODES IN THE 'NEXT' LEVEL, WHICH
  1948. C GROWS FROM THE START OF THE 'NEXT' LEVEL IN LVLLST
  1949. C FORWARDS TOWARD 'ALEVEL'. QUEUED IS OF LENGTH NO MORE
  1950. C THAN THE WIDTH OF THE NEXT LEVEL.
  1951. C LVLLST IS THE LIST OF UNNUMBERED NODES IN THE TREE,
  1952. C ARRANGED BY LEVEL.
  1953. C
  1954. C ==================================================================
  1955. INTEGER I, J, K, PTR, JPTR, KPTR, LPTR, MPTR, PPTR, RPTR,
  1956. 1 MPPTR, JNODE, KNODE, CNODE, LEVEL, LOWDG, UNUSED,
  1957. 2 MXQUE, NNEXT, ASTART, MINDG, LSTART, LWIDTH, ACTIVE,
  1958. 2 QUEUEB, QUEUED, QCOUNT, NCONNC, NACTIV, CDGREE,
  1959. 3 LDGREE, NFINAL, JDGREE, STRTIC, ADDED, TWRKLN,
  1960. 4 LVLLSL, CONNEJ, CONNER, ASTPTR, ACTPTR, ACTIVI,
  1961. 5 ASTRTI, QUEUEI, ACPPTR
  1962. C
  1963. C ------------------------------------------------------------------
  1964. C
  1965. TWRKLN = WRKLEN + NCOMPN + N + DEPTH + 1
  1966. UNUSED = TWRKLN
  1967. C
  1968. ASTART = LVLPTR(1)
  1969. LWIDTH = LVLPTR(2) - ASTART
  1970. ASTART = WRKLEN + 1
  1971. ACTIVE = NXTNUM + LWIDTH + 1
  1972. NACTIV = LWIDTH
  1973. NFINAL = NXTNUM + NCOMPN
  1974. C
  1975. NNEXT = LVLPTR(3) - LVLPTR(2)
  1976. QUEUED = WRKLEN
  1977. QUEUEB = QUEUED
  1978. MXQUE = ACTIVE + LWIDTH
  1979. C
  1980. C ... BUILD FIRST PRIORITY QUEUE 'ACTIVE'
  1981. C
  1982. LOWDG = - (N + 1)
  1983. LPTR = LVLPTR(1)
  1984. DO 200 I = 1, LWIDTH
  1985. NCONNC = 0
  1986. LVLLSL= LVLLST (LPTR)
  1987. JPTR = RSTART (LVLLSL)
  1988. LDGREE = DEGREE(LVLLSL)
  1989. DO 100 J = 1, LDGREE
  1990. CONNEJ = CONNEC (JPTR)
  1991. IF ( LVLNUM (CONNEJ) .EQ. 2 ) NCONNC = NCONNC - 1
  1992. JPTR = JPTR + 1
  1993. 100 CONTINUE
  1994. C
  1995. ACTIVI = ACTIVE + I - 1
  1996. WORK (ACTIVI) = I
  1997. LVLNUM (LVLLSL) = NCONNC
  1998. LOWDG = MAX0 (LOWDG, NCONNC)
  1999. LPTR = LPTR + 1
  2000. 200 CONTINUE
  2001. WORK (ACTIVE-1) = 0
  2002. C
  2003. C -----------------------------------
  2004. C NOW NUMBER NODES LEVEL BY LEVEL ...
  2005. C -----------------------------------
  2006. C
  2007. DO 2000 LEVEL = 1, DEPTH
  2008. C
  2009. C ... NUMBER ALL NODES IN THIS LEVEL
  2010. C
  2011. DO 1100 I = 1, LWIDTH
  2012. PPTR = -1
  2013. PTR = WORK (ACTIVE-1)
  2014. IF (NNEXT .EQ. 0) GO TO 1000
  2015. C
  2016. C ... IF NODES REMAIN IN NEXT, FIND THE EARLIEST NODE
  2017. C IN ACTIVE OF MINIMAL DEGREE.
  2018. C
  2019. MINDG = -(N+1)
  2020. DO 400 J = 1, NACTIV
  2021. ASTPTR = ASTART + PTR
  2022. CNODE = WORK (ASTPTR)
  2023. IF ( LVLNUM (CNODE) .EQ. LOWDG ) GO TO 500
  2024. IF ( LVLNUM (CNODE) .LE. MINDG ) GO TO 300
  2025. MPPTR = PPTR
  2026. MPTR = PTR
  2027. MINDG = LVLNUM (CNODE)
  2028. 300 PPTR = PTR
  2029. ACTPTR = ACTIVE + PTR
  2030. PTR = WORK (ACTPTR)
  2031. 400 CONTINUE
  2032. C
  2033. C ... ESTABLISH PTR AS FIRST MIN DEGREE NODE
  2034. C PPTR AS PREDECESSOR IN LIST.
  2035. C
  2036. PTR = MPTR
  2037. PPTR = MPPTR
  2038. C
  2039. 500 ASTPTR = ASTART + PTR
  2040. CNODE = WORK (ASTPTR)
  2041. LOWDG = LVLNUM (CNODE)
  2042. LVLNUM (CNODE) = 0
  2043. JPTR = RSTART (CNODE)
  2044. C
  2045. C ... UPDATE CONNECTION COUNTS FOR ALL NODES WHICH
  2046. C CONNECT TO CNODE'S NEIGHBORS IN NEXT.
  2047. C
  2048. CDGREE = DEGREE(CNODE)
  2049. STRTIC = QUEUEB
  2050. C
  2051. DO 700 J = 1, CDGREE
  2052. JNODE = CONNEC (JPTR)
  2053. JPTR = JPTR + 1
  2054. IF (LVLNUM (JNODE) .NE. LEVEL+1 ) GO TO 700
  2055. IF (QUEUEB .LT. MXQUE) GO TO 5000
  2056. WORK (QUEUEB) = JNODE
  2057. QUEUEB = QUEUEB - 1
  2058. NNEXT = NNEXT - 1
  2059. LVLNUM (JNODE) = 0
  2060. IF (NACTIV .EQ. 1) GO TO 700
  2061. KPTR = RSTART (JNODE)
  2062. JDGREE = DEGREE (JNODE)
  2063. DO 600 K = 1, JDGREE
  2064. KNODE = CONNEC (KPTR)
  2065. KPTR = KPTR + 1
  2066. IF (LVLNUM (KNODE) .GE. 0) GO TO 600
  2067. LVLNUM (KNODE) = LVLNUM (KNODE) + 1
  2068. IF (LOWDG .LT. LVLNUM(KNODE))
  2069. 1 LOWDG = LVLNUM(KNODE)
  2070. 600 CONTINUE
  2071. 700 CONTINUE
  2072. C
  2073. C ... TO MIMIC THE ALGORITHM AS IMPLEMENTED BY GIBBS,
  2074. C SORT THE NODES JUST ADDED TO THE QUEUE INTO
  2075. C INCREASING ORDER OF ORIGINAL INDEX. (BUT, BECAUSE
  2076. C THE QUEUE IS STORED BACKWARDS IN MEMORY, THE SORT
  2077. C ROUTINE IS CALLED FOR DECREASING INDEX.)
  2078. C
  2079. C TREAT 0, 1 OR 2 NODES ADDED AS SPECIAL CASES
  2080. C
  2081. ADDED = STRTIC - QUEUEB
  2082. IF (ADDED - 2) 1000, 800, 900
  2083. C
  2084. 800 IF (WORK(STRTIC-1) .GT. WORK(STRTIC)) GO TO 1000
  2085. JNODE = WORK(STRTIC)
  2086. WORK(STRTIC) = WORK(STRTIC-1)
  2087. WORK(STRTIC-1) = JNODE
  2088. GO TO 1000
  2089. C
  2090. 900 CALL GPSKCO (ADDED, WORK(QUEUEB+1), ERROR)
  2091. IF (ERROR .NE. 0) GO TO 5500
  2092. C
  2093. C
  2094. C ... NUMBER THIS NODE AND DELETE IT FROM 'ACTIVE'.
  2095. C MARK IT UNAVAILABLE BY CHANGING SIGN OF DEGREE
  2096. C
  2097. 1000 NACTIV = NACTIV - 1
  2098. ASTPTR = ASTART + PTR
  2099. CNODE = WORK (ASTPTR)
  2100. WORK (NXTNUM) = CNODE
  2101. DEGREE (CNODE) = -DEGREE (CNODE)
  2102. NXTNUM = NXTNUM + 1
  2103. C
  2104. C ... DELETE LINK TO THIS NODE FROM LIST
  2105. C
  2106. ACPPTR = ACTIVE + PPTR
  2107. ACTPTR = ACTIVE + PTR
  2108. WORK (ACPPTR) = WORK (ACTPTR)
  2109. 1100 CONTINUE
  2110. C
  2111. C ... NOW MOVE THE QUEUE 'QUEUED' FORWARD, AT THE SAME
  2112. C TIME COMPUTING CONNECTION COUNTS FOR ITS ELEMENTS.
  2113. C THEN DO THE SAME FOR THE REMAINING NODES IN 'NEXT'.
  2114. C
  2115. UNUSED = MIN0 (UNUSED, QUEUEB - MXQUE)
  2116. IF ( NXTNUM .NE. ACTIVE-1 ) GO TO 5100
  2117. IF ( LEVEL .EQ. DEPTH ) GO TO 2000
  2118. LSTART = LVLPTR (LEVEL+1)
  2119. LWIDTH = LVLPTR (LEVEL+2) - LSTART
  2120. ACTIVE = NXTNUM + LWIDTH + 1
  2121. ASTART = ACTIVE + LWIDTH
  2122. NACTIV = LWIDTH
  2123. MXQUE = ASTART + LWIDTH
  2124. IF ( MXQUE .GT. QUEUEB + 1 ) GO TO 5000
  2125. UNUSED = MIN0 (UNUSED, QUEUEB - MXQUE + 1)
  2126. C
  2127. QCOUNT = QUEUED - QUEUEB
  2128. LOWDG = -N-1
  2129. WORK (ACTIVE-1) = 0
  2130. C
  2131. PTR = LSTART
  2132. DO 1600 I = 1, LWIDTH
  2133. C
  2134. C ... CHOOSE NEXT NODE FROM EITHER 'QUEUED' OR 'NEXT'
  2135. C
  2136. IF (I .GT. QCOUNT ) GO TO 1200
  2137. QUEUEI = QUEUED + 1 - I
  2138. CNODE = WORK (QUEUEI)
  2139. GO TO 1300
  2140. C
  2141. 1200 CNODE = LVLLST (PTR)
  2142. PTR = PTR + 1
  2143. IF ( PTR .GT. LVLPTR(LEVEL+2) ) GO TO 5200
  2144. IF (LVLNUM (CNODE) .GT. 0) GO TO 1300
  2145. GO TO 1200
  2146. C
  2147. 1300 IF ( LEVEL+1 .EQ. DEPTH ) GO TO 1500
  2148. C
  2149. RPTR = RSTART (CNODE)
  2150. NCONNC = 0
  2151. JDGREE = DEGREE (CNODE)
  2152. DO 1400 J = 1, JDGREE
  2153. CONNER = CONNEC (RPTR)
  2154. IF ( LVLNUM (CONNER) .EQ. LEVEL+2 )
  2155. 1 NCONNC = NCONNC - 1
  2156. RPTR = RPTR + 1
  2157. 1400 CONTINUE
  2158. LVLNUM (CNODE) = NCONNC
  2159. LOWDG = MAX0 (LOWDG, NCONNC)
  2160. C
  2161. C ... ADD CNODE TO NEW 'ACTIVE' QUEUE
  2162. C
  2163. 1500 ACTIVI = ACTIVE + (I - 1)
  2164. ASTRTI = ASTART + (I - 1)
  2165. WORK (ACTIVI) = I
  2166. WORK (ASTRTI) = CNODE
  2167. 1600 CONTINUE
  2168. C
  2169. IF (DEPTH .EQ. LEVEL+1 ) GO TO 1700
  2170. NNEXT = LVLPTR (LEVEL+3) - LVLPTR (LEVEL+2)
  2171. QUEUED = LSTART - 1 + LWIDTH + WRKLEN
  2172. QUEUEB = QUEUED
  2173. GO TO 2000
  2174. C
  2175. 1700 NNEXT = 0
  2176. C
  2177. 2000 CONTINUE
  2178. C
  2179. IF (NXTNUM .NE. NFINAL) GO TO 5300
  2180. SPACE = MAX0 (SPACE, TWRKLN - UNUSED)
  2181. RETURN
  2182. C
  2183. C
  2184. C ------------------------------------------------------------------
  2185. C
  2186. 5000 SPACE = NACTIV + NNEXT
  2187. ERROR = 160
  2188. RETURN
  2189. C
  2190. 5100 ERROR = 61
  2191. GO TO 5400
  2192. C
  2193. 5200 ERROR = 62
  2194. GO TO 5400
  2195. C
  2196. 5300 ERROR = 63
  2197. C
  2198. 5400 RETURN
  2199. C
  2200. 5500 ERROR = 64
  2201. GO TO 5400
  2202. C
  2203. END
  2204. SUBROUTINE GPSKCL (N, DEGREE, RSTART, CONNEC, INVNUM, NEWNUM,
  2205. 1 OLDNUM, BANDWD, PROFIL, ERROR, SPACE)
  2206. C
  2207. C
  2208. IMPLICIT INTEGER(I-N)
  2209. INTEGER N, RSTART(N), BANDWD, PROFIL, ERROR, SPACE
  2210. C
  2211. CIBM INTEGER *2 DEGREE(N), CONNEC(1), INVNUM(N), NEWNUM(N), OLDNUM(N)
  2212. INTEGER DEGREE(N), CONNEC(1), INVNUM(N), NEWNUM(N), OLDNUM(N)
  2213. C
  2214. C ==================================================================
  2215. C
  2216. C
  2217. C COMPUTE THE BANDWIDTH AND PROFILE FOR THE RENUMBERING GIVEN
  2218. C BY 'INVNUM' AND ALSO FOR THE RENUMBERING GIVEN BY 'OLDNUM'.
  2219. C 'NEWNUM' WILL BE A PERMUTATION VECTOR COPY OF THE NODE
  2220. C LIST 'INVNUM'.
  2221. C
  2222. C ==================================================================
  2223. C
  2224. INTEGER I, J, JPTR, IDGREE, OLDBND, OLDPRO, NEWBND, NEWPRO,
  2225. 1 OLDRWD, NEWRWD, OLDORG, NEWORG, JNODE, INVNMI
  2226. C
  2227. C ------------------------------------------------------------------
  2228. C
  2229. C ... CREATE NEWNUM AS A PERMUTATION VECTOR
  2230. C
  2231. DO 100 I = 1, N
  2232. INVNMI = INVNUM (I)
  2233. NEWNUM (INVNMI) = I
  2234. 100 CONTINUE
  2235. C
  2236. C ... COMPUTE PROFILE AND BANDWIDTH FOR BOTH THE OLD AND THE NEW
  2237. C ORDERINGS.
  2238. C
  2239. OLDBND = 0
  2240. OLDPRO = 0
  2241. NEWBND = 0
  2242. NEWPRO = 0
  2243. C
  2244. DO 300 I = 1, N
  2245. IF (DEGREE(I) .EQ. 0) GO TO 300
  2246. IF (DEGREE(I) .GT. 0) GO TO 6000
  2247. IDGREE = -DEGREE(I)
  2248. DEGREE(I) = IDGREE
  2249. NEWORG = NEWNUM(I)
  2250. OLDORG = OLDNUM(I)
  2251. NEWRWD = 0
  2252. OLDRWD = 0
  2253. JPTR = RSTART (I)
  2254. C
  2255. C ... FIND NEIGHBOR WHICH IS NUMBERED FARTHEST AHEAD OF THE
  2256. C CURRENT NODE.
  2257. C
  2258. DO 200 J = 1, IDGREE
  2259. JNODE = CONNEC(JPTR)
  2260. JPTR = JPTR + 1
  2261. NEWRWD = MAX0 (NEWRWD, NEWORG - NEWNUM(JNODE))
  2262. OLDRWD = MAX0 (OLDRWD, OLDORG - OLDNUM(JNODE))
  2263. 200 CONTINUE
  2264. C
  2265. NEWPRO = NEWPRO + NEWRWD
  2266. NEWBND = MAX0 (NEWBND, NEWRWD)
  2267. OLDPRO = OLDPRO + OLDRWD
  2268. OLDBND = MAX0 (OLDBND, OLDRWD)
  2269. 300 CONTINUE
  2270. C
  2271. C ... IF NEW ORDERING HAS BETTER BANDWIDTH THAN OLD ORDERING,
  2272. C REPLACE OLD ORDERING BY NEW ORDERING
  2273. C
  2274. IF (NEWBND .GT. OLDBND) GO TO 500
  2275. BANDWD = NEWBND
  2276. PROFIL = NEWPRO
  2277. DO 400 I = 1, N
  2278. OLDNUM(I) = NEWNUM(I)
  2279. 400 CONTINUE
  2280. GO TO 600
  2281. C
  2282. C ... RETAIN OLD ORDERING
  2283. C
  2284. 500 BANDWD = OLDBND
  2285. PROFIL = OLDPRO
  2286. C
  2287. 600 RETURN
  2288. C
  2289. C ------------------------------------------------------------------
  2290. C
  2291. 6000 SPACE = -1
  2292. ERROR = 70
  2293. RETURN
  2294. C
  2295. END
  2296. SUBROUTINE GPSKCM (N, DEGREE, RSTART, CONNEC, INVNUM, NEWNUM,
  2297. 1 OLDNUM, BANDWD, PROFIL, ERROR, SPACE)
  2298. C
  2299. C
  2300. IMPLICIT INTEGER(I-N)
  2301. INTEGER N, RSTART(N), BANDWD, PROFIL, ERROR, SPACE
  2302. C
  2303. CIBM INTEGER *2 DEGREE(N), CONNEC(N), INVNUM(N), NEWNUM(N), OLDNUM(N)
  2304. INTEGER DEGREE(N), CONNEC(N), INVNUM(N), NEWNUM(N), OLDNUM(N)
  2305. C
  2306. C ==================================================================
  2307. C
  2308. C
  2309. C COMPUTE THE BANDWIDTH AND PROFILE FOR THE RENUMBERING GIVEN
  2310. C BY 'INVNUM', BY THE REVERSE OF NUMBERING 'INVNUM', AND ALSO
  2311. C BY THE RENUMBERING GIVEN IN 'OLDNUM'.
  2312. C 'NEWNUM' WILL BE A PERMUTATION VECTOR COPY OF THE NODE
  2313. C LIST 'INVNUM'.
  2314. C
  2315. C ==================================================================
  2316. C
  2317. INTEGER I, J, JPTR, IDGREE, OLDBND, OLDPRO, NEWBND, NEWPRO,
  2318. 1 OLDRWD, NEWRWD, OLDORG, NEWORG, JNODE, NRVBND, NRVPRO,
  2319. 2 NRVORG, NRVRWD, INVNMI, NMIP1
  2320. C
  2321. C ------------------------------------------------------------------
  2322. C
  2323. C ... CREATE NEWNUM AS A PERMUTATION VECTOR
  2324. C
  2325. DO 100 I = 1, N
  2326. INVNMI = INVNUM (I)
  2327. NEWNUM (INVNMI) = I
  2328. 100 CONTINUE
  2329. C
  2330. C ... COMPUTE PROFILE AND BANDWIDTH FOR BOTH THE OLD AND THE NEW
  2331. C ORDERINGS.
  2332. C
  2333. OLDBND = 0
  2334. OLDPRO = 0
  2335. NEWBND = 0
  2336. NEWPRO = 0
  2337. NRVBND = 0
  2338. NRVPRO = 0
  2339. C
  2340. DO 300 I = 1, N
  2341. IF (DEGREE(I) .EQ. 0) GO TO 300
  2342. IF (DEGREE(I) .GT. 0) GO TO 6000
  2343. IDGREE = -DEGREE(I)
  2344. DEGREE(I) = IDGREE
  2345. NEWRWD = 0
  2346. OLDRWD = 0
  2347. NRVRWD = 0
  2348. NEWORG = NEWNUM(I)
  2349. OLDORG = OLDNUM(I)
  2350. NRVORG = N - NEWNUM(I) + 1
  2351. JPTR = RSTART (I)
  2352. C
  2353. C ... FIND NEIGHBOR WHICH IS NUMBERED FARTHEST AHEAD OF THE
  2354. C CURRENT NODE.
  2355. C
  2356. DO 200 J = 1, IDGREE
  2357. JNODE = CONNEC(JPTR)
  2358. JPTR = JPTR + 1
  2359. NEWRWD = MAX0 (NEWRWD, NEWORG - NEWNUM(JNODE))
  2360. OLDRWD = MAX0 (OLDRWD, OLDORG - OLDNUM(JNODE))
  2361. NRVRWD = MAX0 (NRVRWD, NRVORG - N + NEWNUM(JNODE) - 1)
  2362. 200 CONTINUE
  2363. C
  2364. NEWPRO = NEWPRO + NEWRWD
  2365. NEWBND = MAX0 (NEWBND, NEWRWD)
  2366. NRVPRO = NRVPRO + NRVRWD
  2367. NRVBND = MAX0 (NRVBND, NRVRWD)
  2368. OLDPRO = OLDPRO + OLDRWD
  2369. OLDBND = MAX0 (OLDBND, OLDRWD)
  2370. 300 CONTINUE
  2371. C
  2372. C ... IF NEW ORDERING HAS BETTER BANDWIDTH THAN OLD ORDERING,
  2373. C REPLACE OLD ORDERING BY NEW ORDERING
  2374. C
  2375. IF ((NEWPRO .GT. OLDPRO) .OR. (NEWPRO .GT. NRVPRO)) GO TO 500
  2376. BANDWD = NEWBND
  2377. PROFIL = NEWPRO
  2378. DO 400 I = 1, N
  2379. OLDNUM(I) = NEWNUM(I)
  2380. 400 CONTINUE
  2381. GO TO 800
  2382. C
  2383. C ... CHECK NEW REVERSED ORDERING FOR BEST PROFILE
  2384. C
  2385. 500 IF (NRVPRO .GT. OLDPRO) GO TO 700
  2386. BANDWD = NRVBND
  2387. PROFIL = NRVPRO
  2388. DO 600 I = 1, N
  2389. OLDNUM(I) = N - NEWNUM(I) + 1
  2390. IF (I .GT. N/2) GO TO 600
  2391. J = INVNUM(I)
  2392. NMIP1 = (N + 1) - I
  2393. INVNUM(I) = INVNUM (NMIP1)
  2394. INVNUM (NMIP1) = J
  2395. 600 CONTINUE
  2396. GO TO 800
  2397. C
  2398. C
  2399. C ... RETAIN OLD ORDERING
  2400. C
  2401. 700 BANDWD = OLDBND
  2402. PROFIL = OLDPRO
  2403. C
  2404. 800 RETURN
  2405. C
  2406. C ------------------------------------------------------------------
  2407. C
  2408. 6000 ERROR = 71
  2409. SPACE = -1
  2410. RETURN
  2411. C
  2412. END
  2413. SUBROUTINE GPSKCN (N, KEY, DATA, ERROR)
  2414. C
  2415. C ==================================================================
  2416. C
  2417. C I N S E R T I O N S O R T
  2418. C
  2419. C INPUT:
  2420. C N -- NUMBER OF ELEMENTS TO BE SORTED
  2421. C KEY -- AN ARRAY OF LENGTH N CONTAINING THE VALUES
  2422. C WHICH ARE TO BE SORTED
  2423. C DATA -- A SECOND ARRAY OF LENGTH N CONTAINING DATA
  2424. C ASSOCIATED WITH THE INDIVIDUAL KEYS.
  2425. C
  2426. C OUTPUT:
  2427. C KEY -- WILL BE ARRANGED SO THAT VALUES ARE IN DECREASING
  2428. C ORDER
  2429. C DATA -- REARRANGED TO CORRESPOND TO REARRANGED KEYS
  2430. C ERROR -- WILL BE ZERO UNLESS THE PROGRAM IS MALFUNCTIONING,
  2431. C IN WHICH CASE IT WILL BE EQUAL TO 1.
  2432. C
  2433. C
  2434. C ==================================================================
  2435. C
  2436. IMPLICIT INTEGER(I-N)
  2437. INTEGER N, ERROR
  2438. C
  2439. CIBM INTEGER *2 KEY(N), DATA(N)
  2440. INTEGER KEY(N), DATA(N)
  2441. C
  2442. C ------------------------------------------------------------------
  2443. C
  2444. INTEGER I, J, D, K, IP1, JM1
  2445. C
  2446. C ------------------------------------------------------------------
  2447. C
  2448. IF (N .EQ. 1) RETURN
  2449. IF (N .LE. 0) GO TO 6000
  2450. C
  2451. ERROR = 0
  2452. C
  2453. C ... INSERTION SORT ... FOR I := N-1 STEP -1 TO 1 DO ...
  2454. C
  2455. 2400 I = N - 1
  2456. IP1 = N
  2457. C
  2458. 2500 IF ( KEY (I) .GE. KEY (IP1) ) GO TO 2800
  2459. C
  2460. C ... OUT OF ORDER ... MOVE UP TO CORRECT PLACE
  2461. C
  2462. K = KEY (I)
  2463. D = DATA (I)
  2464. J = IP1
  2465. JM1 = I
  2466. C
  2467. C ... REPEAT ... UNTIL 'CORRECT PLACE FOR K FOUND'
  2468. C
  2469. 2600 KEY (JM1) = KEY (J)
  2470. DATA (JM1) = DATA (J)
  2471. JM1 = J
  2472. J = J + 1
  2473. IF (J .GT. N) GO TO 2700
  2474. IF (KEY (J) .GT. K) GO TO 2600
  2475. C
  2476. 2700 KEY (JM1) = K
  2477. DATA (JM1) = D
  2478. C
  2479. 2800 IP1 = I
  2480. I = I - 1
  2481. IF ( I .GT. 0 ) GO TO 2500
  2482. C
  2483. 3000 RETURN
  2484. C
  2485. 6000 ERROR = 1
  2486. GO TO 3000
  2487. C
  2488. END
  2489. SUBROUTINE GPSKCO (N, KEY, ERROR)
  2490. C
  2491. C ==================================================================
  2492. C
  2493. C I N S E R T I O N S O R T
  2494. C
  2495. C INPUT:
  2496. C N -- NUMBER OF ELEMENTS TO BE SORTED
  2497. C KEY -- AN ARRAY OF LENGTH N CONTAINING THE VALUES
  2498. C WHICH ARE TO BE SORTED
  2499. C
  2500. C OUTPUT:
  2501. C KEY -- WILL BE ARRANGED SO THAT VALUES ARE IN DECREASING
  2502. C ORDER
  2503. C
  2504. C ==================================================================
  2505. C
  2506. IMPLICIT INTEGER(I-N)
  2507. INTEGER N, ERROR
  2508. C
  2509. CIBM INTEGER *2 KEY(N)
  2510. INTEGER KEY(N)
  2511. C
  2512. C ------------------------------------------------------------------
  2513. C
  2514. INTEGER I, J, K, IP1, JM1
  2515. C
  2516. C ------------------------------------------------------------------
  2517. C
  2518. IF (N .EQ. 1) RETURN
  2519. IF (N .LE. 0) GO TO 6000
  2520. C
  2521. ERROR = 0
  2522. C
  2523. C ... INSERTION SORT ... FOR I := N-1 STEP -1 TO 1 DO ...
  2524. C
  2525. 2400 I = N - 1
  2526. IP1 = N
  2527. C
  2528. 2500 IF ( KEY (I) .GE. KEY (IP1) ) GO TO 2800
  2529. C
  2530. C ... OUT OF ORDER ... MOVE UP TO CORRECT PLACE
  2531. C
  2532. K = KEY (I)
  2533. J = IP1
  2534. JM1 = I
  2535. C
  2536. C ... REPEAT ... UNTIL 'CORRECT PLACE FOR K FOUND'
  2537. C
  2538. 2600 KEY (JM1) = KEY (J)
  2539. JM1 = J
  2540. J = J + 1
  2541. IF (J .GT. N) GO TO 2700
  2542. IF (KEY (J) .GT. K) GO TO 2600
  2543. C
  2544. 2700 KEY (JM1) = K
  2545. C
  2546. 2800 IP1 = I
  2547. I = I - 1
  2548. IF ( I .GT. 0 ) GO TO 2500
  2549. C
  2550. 3000 RETURN
  2551. C
  2552. 6000 ERROR = 1
  2553. GO TO 3000
  2554. C
  2555. END
  2556. SUBROUTINE GPSKCP (N, INDEX, NVEC, DEGREE, ERROR)
  2557. C
  2558. C ==================================================================
  2559. C
  2560. C I N S E R T I O N S O R T
  2561. C
  2562. C INPUT:
  2563. C N -- NUMBER OF ELEMENTS TO BE SORTED
  2564. C INDEX -- AN ARRAY OF LENGTH N CONTAINING THE INDICES
  2565. C WHOSE DEGREES ARE TO BE SORTED
  2566. C DEGREE -- AN NVEC VECTOR, GIVING THE DEGREES OF NODES
  2567. C WHICH ARE TO BE SORTED.
  2568. C
  2569. C OUTPUT:
  2570. C INDEX -- WILL BE ARRANGED SO THAT VALUES ARE IN DECREASING
  2571. C ORDER
  2572. C ERROR -- WILL BE ZERO UNLESS THE PROGRAM IS MALFUNCTIONING,
  2573. C IN WHICH CASE IT WILL BE EQUAL TO 1.
  2574. C
  2575. C ==================================================================
  2576. C
  2577. IMPLICIT INTEGER(I-N)
  2578. INTEGER N, NVEC, ERROR
  2579. C
  2580. CIBM INTEGER *2 INDEX(N), DEGREE(NVEC)
  2581. INTEGER INDEX(N), DEGREE(NVEC)
  2582. C
  2583. C ------------------------------------------------------------------
  2584. C
  2585. INTEGER I, J, V, IP1, JM1, INDEXI, INDXI1, INDEXJ
  2586. C
  2587. C ------------------------------------------------------------------
  2588. C
  2589. IF (N .EQ. 1) RETURN
  2590. IF (N .LE. 0) GO TO 6000
  2591. C
  2592. ERROR = 0
  2593. C
  2594. C ------------------------------------------------------------------
  2595. C INSERTION SORT THE ENTIRE FILE
  2596. C ------------------------------------------------------------------
  2597. C
  2598. C
  2599. C ... INSERTION SORT ... FOR I := N-1 STEP -1 TO 1 DO ...
  2600. C
  2601. 2400 I = N - 1
  2602. IP1 = N
  2603. C
  2604. 2500 INDEXI = INDEX (I)
  2605. INDXI1 = INDEX (IP1)
  2606. IF ( DEGREE(INDEXI) .GE. DEGREE(INDXI1) ) GO TO 2800
  2607. C
  2608. C ... OUT OF ORDER ... MOVE UP TO CORRECT PLACE
  2609. C
  2610. V = DEGREE (INDEXI)
  2611. J = IP1
  2612. JM1 = I
  2613. INDEXJ = INDEX (J)
  2614. C
  2615. C ... REPEAT ... UNTIL 'CORRECT PLACE FOR V FOUND'
  2616. C
  2617. 2600 INDEX (JM1) = INDEXJ
  2618. JM1 = J
  2619. J = J + 1
  2620. IF (J .GT. N) GO TO 2700
  2621. INDEXJ = INDEX (J)
  2622. IF (DEGREE(INDEXJ) .GT. V) GO TO 2600
  2623. C
  2624. 2700 INDEX (JM1) = INDEXI
  2625. C
  2626. 2800 IP1 = I
  2627. I = I - 1
  2628. IF ( I .GT. 0 ) GO TO 2500
  2629. C
  2630. 3000 RETURN
  2631. C
  2632. 6000 ERROR = 1
  2633. GO TO 3000
  2634. C
  2635. END
  2636. SUBROUTINE GPSKCQ (N, INDEX, NVEC, DEGREE, ERROR)
  2637. C
  2638. C ==================================================================
  2639. C
  2640. C I N S E R T I O N S O R T
  2641. C
  2642. C INPUT:
  2643. C N -- NUMBER OF ELEMENTS TO BE SORTED
  2644. C INDEX -- AN ARRAY OF LENGTH N CONTAINING THE INDICES
  2645. C WHOSE DEGREES ARE TO BE SORTED
  2646. C DEGREE -- AN NVEC VECTOR, GIVING THE DEGREES OF NODES
  2647. C WHICH ARE TO BE SORTED.
  2648. C
  2649. C OUTPUT:
  2650. C INDEX -- WILL BE ARRANGED SO THAT VALUES ARE IN INCREASING
  2651. C ORDER
  2652. C ERROR -- WILL BE ZERO UNLESS THE PROGRAM IS MALFUNCTIONING,
  2653. C IN WHICH CASE IT WILL BE EQUAL TO 1.
  2654. C
  2655. C ==================================================================
  2656. C
  2657. IMPLICIT INTEGER(I-N)
  2658. INTEGER N, NVEC, ERROR
  2659. C
  2660. CIBM INTEGER *2 INDEX(N), DEGREE(NVEC)
  2661. INTEGER INDEX(N), DEGREE(NVEC)
  2662. C
  2663. C ------------------------------------------------------------------
  2664. C
  2665. INTEGER I, J, V, INDEXI, INDXI1, INDEXJ, IP1, JM1
  2666. C
  2667. C ------------------------------------------------------------------
  2668. C
  2669. IF (N .EQ. 1) RETURN
  2670. IF (N .LE. 0) GO TO 6000
  2671. C
  2672. ERROR = 0
  2673. C
  2674. C ------------------------------------------------------------------
  2675. C INSERTION SORT THE ENTIRE FILE
  2676. C ------------------------------------------------------------------
  2677. C
  2678. C
  2679. C ... INSERTION SORT ... FOR I := N-1 STEP -1 TO 1 DO ...
  2680. C
  2681. 2400 I = N - 1
  2682. IP1 = N
  2683. C
  2684. 2500 INDEXI = INDEX (I)
  2685. INDXI1 = INDEX (IP1)
  2686. IF ( DEGREE(INDEXI) .LE. DEGREE(INDXI1) ) GO TO 2800
  2687. C
  2688. C ... OUT OF ORDER ... MOVE UP TO CORRECT PLACE
  2689. C
  2690. V = DEGREE (INDEXI)
  2691. J = IP1
  2692. JM1 = I
  2693. INDEXJ = INDEX (J)
  2694. C
  2695. C ... REPEAT ... UNTIL 'CORRECT PLACE FOR V FOUND'
  2696. C
  2697. 2600 INDEX (JM1) = INDEXJ
  2698. JM1 = J
  2699. J = J + 1
  2700. IF (J .GT. N) GO TO 2700
  2701. INDEXJ = INDEX (J)
  2702. IF (DEGREE(INDEXJ) .LT. V) GO TO 2600
  2703. C
  2704. 2700 INDEX (JM1) = INDEXI
  2705. C
  2706. 2800 IP1 = I
  2707. I = I - 1
  2708. IF ( I .GT. 0 ) GO TO 2500
  2709. C
  2710. 3000 RETURN
  2711. C
  2712. 6000 ERROR = 1
  2713. GO TO 3000
  2714. C
  2715. END
  2716.  
  2717.  
  2718.  
  2719.  
  2720.  
  2721.  

© Cast3M 2003 - Tous droits réservés.
Mentions légales