spsort.f 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. *DECK SPSORT
  2. SUBROUTINE SPSORT (X, N, IPERM, KFLAG, IER)
  3. C***BEGIN PROLOGUE SPSORT
  4. C***PURPOSE Return the permutation vector generated by sorting a given
  5. C array and, optionally, rearrange the elements of the array.
  6. C The array may be sorted in increasing or decreasing order.
  7. C A slightly modified quicksort algorithm is used.
  8. C***LIBRARY SLATEC
  9. C***CATEGORY N6A1B, N6A2B
  10. C***TYPE SINGLE PRECISION (SPSORT-S, DPSORT-D, IPSORT-I, HPSORT-H)
  11. C***KEYWORDS NUMBER SORTING, PASSIVE SORTING, SINGLETON QUICKSORT, SORT
  12. C***AUTHOR Jones, R. E., (SNLA)
  13. C Rhoads, G. S., (NBS)
  14. C Wisniewski, J. A., (SNLA)
  15. C***DESCRIPTION
  16. C
  17. C SPSORT returns the permutation vector IPERM generated by sorting
  18. C the array X and, optionally, rearranges the values in X. X may
  19. C be sorted in increasing or decreasing order. A slightly modified
  20. C quicksort algorithm is used.
  21. C
  22. C IPERM is such that X(IPERM(I)) is the Ith value in the rearrangement
  23. C of X. IPERM may be applied to another array by calling IPPERM,
  24. C SPPERM, DPPERM or HPPERM.
  25. C
  26. C The main difference between SPSORT and its active sorting equivalent
  27. C SSORT is that the data are referenced indirectly rather than
  28. C directly. Therefore, SPSORT should require approximately twice as
  29. C long to execute as SSORT. However, SPSORT is more general.
  30. C
  31. C Description of Parameters
  32. C X - input/output -- real array of values to be sorted.
  33. C If ABS(KFLAG) = 2, then the values in X will be
  34. C rearranged on output; otherwise, they are unchanged.
  35. C N - input -- number of values in array X to be sorted.
  36. C IPERM - output -- permutation array such that IPERM(I) is the
  37. C index of the value in the original order of the
  38. C X array that is in the Ith location in the sorted
  39. C order.
  40. C KFLAG - input -- control parameter:
  41. C = 2 means return the permutation vector resulting from
  42. C sorting X in increasing order and sort X also.
  43. C = 1 means return the permutation vector resulting from
  44. C sorting X in increasing order and do not sort X.
  45. C = -1 means return the permutation vector resulting from
  46. C sorting X in decreasing order and do not sort X.
  47. C = -2 means return the permutation vector resulting from
  48. C sorting X in decreasing order and sort X also.
  49. C IER - output -- error indicator:
  50. C = 0 if no error,
  51. C = 1 if N is zero or negative,
  52. C = 2 if KFLAG is not 2, 1, -1, or -2.
  53. C***REFERENCES R. C. Singleton, Algorithm 347, An efficient algorithm
  54. C for sorting with minimal storage, Communications of
  55. C the ACM, 12, 3 (1969), pp. 185-187.
  56. C***ROUTINES CALLED XERMSG
  57. C***REVISION HISTORY (YYMMDD)
  58. C 761101 DATE WRITTEN
  59. C 761118 Modified by John A. Wisniewski to use the Singleton
  60. C quicksort algorithm.
  61. C 870423 Modified by Gregory S. Rhoads for passive sorting with the
  62. C option for the rearrangement of the original data.
  63. C 890620 Algorithm for rearranging the data vector corrected by R.
  64. C Boisvert.
  65. C 890622 Prologue upgraded to Version 4.0 style by D. Lozier.
  66. C 891128 Error when KFLAG.LT.0 and N=1 corrected by R. Boisvert.
  67. C 920507 Modified by M. McClain to revise prologue text.
  68. C 920818 Declarations section rebuilt and code restructured to use
  69. C IF-THEN-ELSE-ENDIF. (SMR, WRB)
  70. C***END PROLOGUE SPSORT
  71. C .. Scalar Arguments ..
  72. INTEGER IER, KFLAG, N
  73. C .. Array Arguments ..
  74. REAL X(*)
  75. INTEGER IPERM(*)
  76. C .. Local Scalars ..
  77. REAL R, TEMP
  78. INTEGER I, IJ, INDX, INDX0, ISTRT, J, K, KK, L, LM, LMT, M, NN
  79. C .. Local Arrays ..
  80. INTEGER IL(21), IU(21)
  81. C .. External Subroutines ..
  82. EXTERNAL XERMSG
  83. C .. Intrinsic Functions ..
  84. INTRINSIC ABS, INT
  85. C***FIRST EXECUTABLE STATEMENT SPSORT
  86. IER = 0
  87. NN = N
  88. IF (NN .LT. 1) THEN
  89. IER = 1
  90. CALL XERMSG ('SLATEC', 'SPSORT',
  91. + 'The number of values to be sorted, N, is not positive.',
  92. + IER, 1)
  93. RETURN
  94. ENDIF
  95. KK = ABS(KFLAG)
  96. IF (KK.NE.1 .AND. KK.NE.2) THEN
  97. IER = 2
  98. CALL XERMSG ('SLATEC', 'SPSORT',
  99. + 'The sort control parameter, KFLAG, is not 2, 1, -1, or -2.',
  100. + IER, 1)
  101. RETURN
  102. ENDIF
  103. C
  104. C Initialize permutation vector
  105. C
  106. DO 10 I=1,NN
  107. IPERM(I) = I
  108. 10 CONTINUE
  109. C
  110. C Return if only one value is to be sorted
  111. C
  112. IF (NN .EQ. 1) RETURN
  113. C
  114. C Alter array X to get decreasing order if needed
  115. C
  116. IF (KFLAG .LE. -1) THEN
  117. DO 20 I=1,NN
  118. X(I) = -X(I)
  119. 20 CONTINUE
  120. ENDIF
  121. C
  122. C Sort X only
  123. C
  124. M = 1
  125. I = 1
  126. J = NN
  127. R = .375E0
  128. C
  129. 30 IF (I .EQ. J) GO TO 80
  130. IF (R .LE. 0.5898437E0) THEN
  131. R = R+3.90625E-2
  132. ELSE
  133. R = R-0.21875E0
  134. ENDIF
  135. C
  136. 40 K = I
  137. C
  138. C Select a central element of the array and save it in location L
  139. C
  140. IJ = I + INT((J-I)*R)
  141. LM = IPERM(IJ)
  142. C
  143. C If first element of array is greater than LM, interchange with LM
  144. C
  145. IF (X(IPERM(I)) .GT. X(LM)) THEN
  146. IPERM(IJ) = IPERM(I)
  147. IPERM(I) = LM
  148. LM = IPERM(IJ)
  149. ENDIF
  150. L = J
  151. C
  152. C If last element of array is less than LM, interchange with LM
  153. C
  154. IF (X(IPERM(J)) .LT. X(LM)) THEN
  155. IPERM(IJ) = IPERM(J)
  156. IPERM(J) = LM
  157. LM = IPERM(IJ)
  158. C
  159. C If first element of array is greater than LM, interchange
  160. C with LM
  161. C
  162. IF (X(IPERM(I)) .GT. X(LM)) THEN
  163. IPERM(IJ) = IPERM(I)
  164. IPERM(I) = LM
  165. LM = IPERM(IJ)
  166. ENDIF
  167. ENDIF
  168. GO TO 60
  169. 50 LMT = IPERM(L)
  170. IPERM(L) = IPERM(K)
  171. IPERM(K) = LMT
  172. C
  173. C Find an element in the second half of the array which is smaller
  174. C than LM
  175. C
  176. 60 L = L-1
  177. IF (X(IPERM(L)) .GT. X(LM)) GO TO 60
  178. C
  179. C Find an element in the first half of the array which is greater
  180. C than LM
  181. C
  182. 70 K = K+1
  183. IF (X(IPERM(K)) .LT. X(LM)) GO TO 70
  184. C
  185. C Interchange these elements
  186. C
  187. IF (K .LE. L) GO TO 50
  188. C
  189. C Save upper and lower subscripts of the array yet to be sorted
  190. C
  191. IF (L-I .GT. J-K) THEN
  192. IL(M) = I
  193. IU(M) = L
  194. I = K
  195. M = M+1
  196. ELSE
  197. IL(M) = K
  198. IU(M) = J
  199. J = L
  200. M = M+1
  201. ENDIF
  202. GO TO 90
  203. C
  204. C Begin again on another portion of the unsorted array
  205. C
  206. 80 M = M-1
  207. IF (M .EQ. 0) GO TO 120
  208. I = IL(M)
  209. J = IU(M)
  210. C
  211. 90 IF (J-I .GE. 1) GO TO 40
  212. IF (I .EQ. 1) GO TO 30
  213. I = I-1
  214. C
  215. 100 I = I+1
  216. IF (I .EQ. J) GO TO 80
  217. LM = IPERM(I+1)
  218. IF (X(IPERM(I)) .LE. X(LM)) GO TO 100
  219. K = I
  220. C
  221. 110 IPERM(K+1) = IPERM(K)
  222. K = K-1
  223. C
  224. IF (X(LM) .LT. X(IPERM(K))) GO TO 110
  225. IPERM(K+1) = LM
  226. GO TO 100
  227. C
  228. C Clean up
  229. C
  230. 120 IF (KFLAG .LE. -1) THEN
  231. DO 130 I=1,NN
  232. X(I) = -X(I)
  233. 130 CONTINUE
  234. ENDIF
  235. C
  236. C Rearrange the values of X if desired
  237. C
  238. IF (KK .EQ. 2) THEN
  239. C
  240. C Use the IPERM vector as a flag.
  241. C If IPERM(I) < 0, then the I-th value is in correct location
  242. C
  243. DO 150 ISTRT=1,NN
  244. IF (IPERM(ISTRT) .GE. 0) THEN
  245. INDX = ISTRT
  246. INDX0 = INDX
  247. TEMP = X(ISTRT)
  248. 140 IF (IPERM(INDX) .GT. 0) THEN
  249. X(INDX) = X(IPERM(INDX))
  250. INDX0 = INDX
  251. IPERM(INDX) = -IPERM(INDX)
  252. INDX = ABS(IPERM(INDX))
  253. GO TO 140
  254. ENDIF
  255. X(INDX0) = TEMP
  256. ENDIF
  257. 150 CONTINUE
  258. C
  259. C Revert the signs of the IPERM values
  260. C
  261. DO 160 I=1,NN
  262. IPERM(I) = -IPERM(I)
  263. 160 CONTINUE
  264. C
  265. ENDIF
  266. C
  267. RETURN
  268. END