hpsort.f 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. *DECK HPSORT
  2. SUBROUTINE HPSORT (HX, N, STRBEG, STREND, IPERM, KFLAG, WORK, IER)
  3. C***BEGIN PROLOGUE HPSORT
  4. C***PURPOSE Return the permutation vector generated by sorting a
  5. C substring within a character array and, optionally,
  6. C rearrange the elements of the array. The array may be
  7. C sorted in forward or reverse lexicographical order. A
  8. C slightly modified quicksort algorithm is used.
  9. C***LIBRARY SLATEC
  10. C***CATEGORY N6A1C, N6A2C
  11. C***TYPE CHARACTER (SPSORT-S, DPSORT-D, IPSORT-I, HPSORT-H)
  12. C***KEYWORDS PASSIVE SORTING, SINGLETON QUICKSORT, SORT, STRING SORTING
  13. C***AUTHOR Jones, R. E., (SNLA)
  14. C Rhoads, G. S., (NBS)
  15. C Sullivan, F. E., (NBS)
  16. C Wisniewski, J. A., (SNLA)
  17. C***DESCRIPTION
  18. C
  19. C HPSORT returns the permutation vector IPERM generated by sorting
  20. C the substrings beginning with the character STRBEG and ending with
  21. C the character STREND within the strings in array HX and, optionally,
  22. C rearranges the strings in HX. HX may be sorted in increasing or
  23. C decreasing lexicographical order. A slightly modified quicksort
  24. C algorithm is used.
  25. C
  26. C IPERM is such that HX(IPERM(I)) is the Ith value in the
  27. C rearrangement of HX. IPERM may be applied to another array by
  28. C calling IPPERM, SPPERM, DPPERM or HPPERM.
  29. C
  30. C An active sort of numerical data is expected to execute somewhat
  31. C more quickly than a passive sort because there is no need to use
  32. C indirect references. But for the character data in HPSORT, integers
  33. C in the IPERM vector are manipulated rather than the strings in HX.
  34. C Moving integers may be enough faster than moving character strings
  35. C to more than offset the penalty of indirect referencing.
  36. C
  37. C Description of Parameters
  38. C HX - input/output -- array of type character to be sorted.
  39. C For example, to sort a 80 element array of names,
  40. C each of length 6, declare HX as character HX(100)*6.
  41. C If ABS(KFLAG) = 2, then the values in HX will be
  42. C rearranged on output; otherwise, they are unchanged.
  43. C N - input -- number of values in array HX to be sorted.
  44. C STRBEG - input -- the index of the initial character in
  45. C the string HX that is to be sorted.
  46. C STREND - input -- the index of the final character in
  47. C the string HX that is to be sorted.
  48. C IPERM - output -- permutation array such that IPERM(I) is the
  49. C index of the string in the original order of the
  50. C HX array that is in the Ith location in the sorted
  51. C order.
  52. C KFLAG - input -- control parameter:
  53. C = 2 means return the permutation vector resulting from
  54. C sorting HX in lexicographical order and sort HX also.
  55. C = 1 means return the permutation vector resulting from
  56. C sorting HX in lexicographical order and do not sort
  57. C HX.
  58. C = -1 means return the permutation vector resulting from
  59. C sorting HX in reverse lexicographical order and do
  60. C not sort HX.
  61. C = -2 means return the permutation vector resulting from
  62. C sorting HX in reverse lexicographical order and sort
  63. C HX also.
  64. C WORK - character variable which must have a length specification
  65. C at least as great as that of HX.
  66. C IER - output -- error indicator:
  67. C = 0 if no error,
  68. C = 1 if N is zero or negative,
  69. C = 2 if KFLAG is not 2, 1, -1, or -2,
  70. C = 3 if work array is not long enough,
  71. C = 4 if string beginning is beyond its end,
  72. C = 5 if string beginning is out-of-range,
  73. C = 6 if string end is out-of-range.
  74. C
  75. C E X A M P L E O F U S E
  76. C
  77. C CHARACTER*2 HX, W
  78. C INTEGER STRBEG, STREND
  79. C DIMENSION HX(10), IPERM(10)
  80. C DATA (HX(I),I=1,10)/ '05','I ',' I',' ','Rs','9R','R9','89',
  81. C 1 ',*','N"'/
  82. C DATA STRBEG, STREND / 1, 2 /
  83. C CALL HPSORT (HX,10,STRBEG,STREND,IPERM,1,W)
  84. C PRINT 100, (HX(IPERM(I)),I=1,10)
  85. C 100 FORMAT (2X, A2)
  86. C STOP
  87. C END
  88. C
  89. C***REFERENCES R. C. Singleton, Algorithm 347, An efficient algorithm
  90. C for sorting with minimal storage, Communications of
  91. C the ACM, 12, 3 (1969), pp. 185-187.
  92. C***ROUTINES CALLED XERMSG
  93. C***REVISION HISTORY (YYMMDD)
  94. C 761101 DATE WRITTEN
  95. C 761118 Modified by John A. Wisniewski to use the Singleton
  96. C quicksort algorithm.
  97. C 811001 Modified by Francis Sullivan for string data.
  98. C 850326 Documentation slightly modified by D. Kahaner.
  99. C 870423 Modified by Gregory S. Rhoads for passive sorting with the
  100. C option for the rearrangement of the original data.
  101. C 890620 Algorithm for rearranging the data vector corrected by R.
  102. C Boisvert.
  103. C 890622 Prologue upgraded to Version 4.0 style by D. Lozier.
  104. C 920507 Modified by M. McClain to revise prologue text.
  105. C 920818 Declarations section rebuilt and code restructured to use
  106. C IF-THEN-ELSE-ENDIF. (SMR, WRB)
  107. C***END PROLOGUE HPSORT
  108. C .. Scalar Arguments ..
  109. INTEGER IER, KFLAG, N, STRBEG, STREND
  110. CHARACTER * (*) WORK
  111. C .. Array Arguments ..
  112. INTEGER IPERM(*)
  113. CHARACTER * (*) HX(*)
  114. C .. Local Scalars ..
  115. REAL R
  116. INTEGER I, IJ, INDX, INDX0, IR, ISTRT, J, K, KK, L, LM, LMT, M,
  117. + NN, NN2
  118. C .. Local Arrays ..
  119. INTEGER IL(21), IU(21)
  120. C .. External Subroutines ..
  121. EXTERNAL XERMSG
  122. C .. Intrinsic Functions ..
  123. INTRINSIC ABS, INT, LEN
  124. C***FIRST EXECUTABLE STATEMENT HPSORT
  125. IER = 0
  126. NN = N
  127. IF (NN .LT. 1) THEN
  128. IER = 1
  129. CALL XERMSG ('SLATEC', 'HPSORT',
  130. + 'The number of values to be sorted, N, is not positive.',
  131. + IER, 1)
  132. RETURN
  133. ENDIF
  134. KK = ABS(KFLAG)
  135. IF (KK.NE.1 .AND. KK.NE.2) THEN
  136. IER = 2
  137. CALL XERMSG ('SLATEC', 'HPSORT',
  138. + 'The sort control parameter, KFLAG, is not 2, 1, -1, or -2.',
  139. + IER, 1)
  140. RETURN
  141. ENDIF
  142. C
  143. IF(LEN(WORK) .LT. LEN(HX(1))) THEN
  144. IER = 3
  145. CALL XERMSG ('SLATEC',' HPSORT',
  146. + 'The length of the work variable, WORK, is too short.',
  147. + IER, 1)
  148. RETURN
  149. ENDIF
  150. IF (STRBEG .GT. STREND) THEN
  151. IER = 4
  152. CALL XERMSG ('SLATEC', 'HPSORT',
  153. + 'The string beginning, STRBEG, is beyond its end, STREND.',
  154. + IER, 1)
  155. RETURN
  156. ENDIF
  157. IF (STRBEG .LT. 1 .OR. STRBEG .GT. LEN(HX(1))) THEN
  158. IER = 5
  159. CALL XERMSG ('SLATEC', 'HPSORT',
  160. + 'The string beginning, STRBEG, is out-of-range.',
  161. + IER, 1)
  162. RETURN
  163. ENDIF
  164. IF (STREND .LT. 1 .OR. STREND .GT. LEN(HX(1))) THEN
  165. IER = 6
  166. CALL XERMSG ('SLATEC', 'HPSORT',
  167. + 'The string end, STREND, is out-of-range.',
  168. + IER, 1)
  169. RETURN
  170. ENDIF
  171. C
  172. C Initialize permutation vector
  173. C
  174. DO 10 I=1,NN
  175. IPERM(I) = I
  176. 10 CONTINUE
  177. C
  178. C Return if only one value is to be sorted
  179. C
  180. IF (NN .EQ. 1) RETURN
  181. C
  182. C Sort HX only
  183. C
  184. M = 1
  185. I = 1
  186. J = NN
  187. R = .375E0
  188. C
  189. 20 IF (I .EQ. J) GO TO 70
  190. IF (R .LE. 0.5898437E0) THEN
  191. R = R+3.90625E-2
  192. ELSE
  193. R = R-0.21875E0
  194. ENDIF
  195. C
  196. 30 K = I
  197. C
  198. C Select a central element of the array and save it in location L
  199. C
  200. IJ = I + INT((J-I)*R)
  201. LM = IPERM(IJ)
  202. C
  203. C If first element of array is greater than LM, interchange with LM
  204. C
  205. IF (HX(IPERM(I))(STRBEG:STREND) .GT. HX(LM)(STRBEG:STREND)) THEN
  206. IPERM(IJ) = IPERM(I)
  207. IPERM(I) = LM
  208. LM = IPERM(IJ)
  209. ENDIF
  210. L = J
  211. C
  212. C If last element of array is less than LM, interchange with LM
  213. C
  214. IF (HX(IPERM(J))(STRBEG:STREND) .LT. HX(LM)(STRBEG:STREND)) THEN
  215. IPERM(IJ) = IPERM(J)
  216. IPERM(J) = LM
  217. LM = IPERM(IJ)
  218. C
  219. C If first element of array is greater than LM, interchange
  220. C with LM
  221. C
  222. IF (HX(IPERM(I))(STRBEG:STREND) .GT. HX(LM)(STRBEG:STREND))
  223. + THEN
  224. IPERM(IJ) = IPERM(I)
  225. IPERM(I) = LM
  226. LM = IPERM(IJ)
  227. ENDIF
  228. ENDIF
  229. GO TO 50
  230. 40 LMT = IPERM(L)
  231. IPERM(L) = IPERM(K)
  232. IPERM(K) = LMT
  233. C
  234. C Find an element in the second half of the array which is smaller
  235. C than LM
  236. C
  237. 50 L = L-1
  238. IF (HX(IPERM(L))(STRBEG:STREND) .GT. HX(LM)(STRBEG:STREND))
  239. + GO TO 50
  240. C
  241. C Find an element in the first half of the array which is greater
  242. C than LM
  243. C
  244. 60 K = K+1
  245. IF (HX(IPERM(K))(STRBEG:STREND) .LT. HX(LM)(STRBEG:STREND))
  246. + GO TO 60
  247. C
  248. C Interchange these elements
  249. C
  250. IF (K .LE. L) GO TO 40
  251. C
  252. C Save upper and lower subscripts of the array yet to be sorted
  253. C
  254. IF (L-I .GT. J-K) THEN
  255. IL(M) = I
  256. IU(M) = L
  257. I = K
  258. M = M+1
  259. ELSE
  260. IL(M) = K
  261. IU(M) = J
  262. J = L
  263. M = M+1
  264. ENDIF
  265. GO TO 80
  266. C
  267. C Begin again on another portion of the unsorted array
  268. C
  269. 70 M = M-1
  270. IF (M .EQ. 0) GO TO 110
  271. I = IL(M)
  272. J = IU(M)
  273. C
  274. 80 IF (J-I .GE. 1) GO TO 30
  275. IF (I .EQ. 1) GO TO 20
  276. I = I-1
  277. C
  278. 90 I = I+1
  279. IF (I .EQ. J) GO TO 70
  280. LM = IPERM(I+1)
  281. IF (HX(IPERM(I))(STRBEG:STREND) .LE. HX(LM)(STRBEG:STREND))
  282. + GO TO 90
  283. K = I
  284. C
  285. 100 IPERM(K+1) = IPERM(K)
  286. K = K-1
  287. C
  288. IF (HX(LM)(STRBEG:STREND) .LT. HX(IPERM(K))(STRBEG:STREND))
  289. + GO TO 100
  290. IPERM(K+1) = LM
  291. GO TO 90
  292. C
  293. C Clean up
  294. C
  295. 110 IF (KFLAG .LE. -1) THEN
  296. C
  297. C Alter array to get reverse order, if necessary
  298. C
  299. NN2 = NN/2
  300. DO 120 I=1,NN2
  301. IR = NN-I+1
  302. LM = IPERM(I)
  303. IPERM(I) = IPERM(IR)
  304. IPERM(IR) = LM
  305. 120 CONTINUE
  306. ENDIF
  307. C
  308. C Rearrange the values of HX if desired
  309. C
  310. IF (KK .EQ. 2) THEN
  311. C
  312. C Use the IPERM vector as a flag.
  313. C If IPERM(I) < 0, then the I-th value is in correct location
  314. C
  315. DO 140 ISTRT=1,NN
  316. IF (IPERM(ISTRT) .GE. 0) THEN
  317. INDX = ISTRT
  318. INDX0 = INDX
  319. WORK = HX(ISTRT)
  320. 130 IF (IPERM(INDX) .GT. 0) THEN
  321. HX(INDX) = HX(IPERM(INDX))
  322. INDX0 = INDX
  323. IPERM(INDX) = -IPERM(INDX)
  324. INDX = ABS(IPERM(INDX))
  325. GO TO 130
  326. ENDIF
  327. HX(INDX0) = WORK
  328. ENDIF
  329. 140 CONTINUE
  330. C
  331. C Revert the signs of the IPERM values
  332. C
  333. DO 150 I=1,NN
  334. IPERM(I) = -IPERM(I)
  335. 150 CONTINUE
  336. C
  337. ENDIF
  338. C
  339. RETURN
  340. END