dpsort.f 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. *DECK DPSORT
  2. SUBROUTINE DPSORT (DX, N, IPERM, KFLAG, IER)
  3. C***BEGIN PROLOGUE DPSORT
  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 DOUBLE 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 DPSORT returns the permutation vector IPERM generated by sorting
  18. C the array DX and, optionally, rearranges the values in DX. DX 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 DX(IPERM(I)) is the Ith value in the
  23. C rearrangement of DX. IPERM may be applied to another array by
  24. C calling IPPERM, SPPERM, DPPERM or HPPERM.
  25. C
  26. C The main difference between DPSORT and its active sorting equivalent
  27. C DSORT is that the data are referenced indirectly rather than
  28. C directly. Therefore, DPSORT should require approximately twice as
  29. C long to execute as DSORT. However, DPSORT is more general.
  30. C
  31. C Description of Parameters
  32. C DX - input/output -- double precision array of values to be
  33. C sorted. If ABS(KFLAG) = 2, then the values in DX will be
  34. C rearranged on output; otherwise, they are unchanged.
  35. C N - input -- number of values in array DX 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 DX 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 DX in increasing order and sort DX also.
  43. C = 1 means return the permutation vector resulting from
  44. C sorting DX in increasing order and do not sort DX.
  45. C = -1 means return the permutation vector resulting from
  46. C sorting DX in decreasing order and do not sort DX.
  47. C = -2 means return the permutation vector resulting from
  48. C sorting DX in decreasing order and sort DX 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 890619 Double precision version of SPSORT created by D. W. Lozier.
  64. C 890620 Algorithm for rearranging the data vector corrected by R.
  65. C Boisvert.
  66. C 890622 Prologue upgraded to Version 4.0 style by D. Lozier.
  67. C 891128 Error when KFLAG.LT.0 and N=1 corrected by R. Boisvert.
  68. C 920507 Modified by M. McClain to revise prologue text.
  69. C 920818 Declarations section rebuilt and code restructured to use
  70. C IF-THEN-ELSE-ENDIF. (SMR, WRB)
  71. C***END PROLOGUE DPSORT
  72. C .. Scalar Arguments ..
  73. INTEGER IER, KFLAG, N
  74. C .. Array Arguments ..
  75. DOUBLE PRECISION DX(*)
  76. INTEGER IPERM(*)
  77. C .. Local Scalars ..
  78. DOUBLE PRECISION R, TEMP
  79. INTEGER I, IJ, INDX, INDX0, ISTRT, J, K, KK, L, LM, LMT, M, NN
  80. C .. Local Arrays ..
  81. INTEGER IL(21), IU(21)
  82. C .. External Subroutines ..
  83. EXTERNAL XERMSG
  84. C .. Intrinsic Functions ..
  85. INTRINSIC ABS, INT
  86. C***FIRST EXECUTABLE STATEMENT DPSORT
  87. IER = 0
  88. NN = N
  89. IF (NN .LT. 1) THEN
  90. IER = 1
  91. CALL XERMSG ('SLATEC', 'DPSORT',
  92. + 'The number of values to be sorted, N, is not positive.',
  93. + IER, 1)
  94. RETURN
  95. ENDIF
  96. C
  97. KK = ABS(KFLAG)
  98. IF (KK.NE.1 .AND. KK.NE.2) THEN
  99. IER = 2
  100. CALL XERMSG ('SLATEC', 'DPSORT',
  101. + 'The sort control parameter, KFLAG, is not 2, 1, -1, or -2.',
  102. + IER, 1)
  103. RETURN
  104. ENDIF
  105. C
  106. C Initialize permutation vector
  107. C
  108. DO 10 I=1,NN
  109. IPERM(I) = I
  110. 10 CONTINUE
  111. C
  112. C Return if only one value is to be sorted
  113. C
  114. IF (NN .EQ. 1) RETURN
  115. C
  116. C Alter array DX to get decreasing order if needed
  117. C
  118. IF (KFLAG .LE. -1) THEN
  119. DO 20 I=1,NN
  120. DX(I) = -DX(I)
  121. 20 CONTINUE
  122. ENDIF
  123. C
  124. C Sort DX only
  125. C
  126. M = 1
  127. I = 1
  128. J = NN
  129. R = .375D0
  130. C
  131. 30 IF (I .EQ. J) GO TO 80
  132. IF (R .LE. 0.5898437D0) THEN
  133. R = R+3.90625D-2
  134. ELSE
  135. R = R-0.21875D0
  136. ENDIF
  137. C
  138. 40 K = I
  139. C
  140. C Select a central element of the array and save it in location L
  141. C
  142. IJ = I + INT((J-I)*R)
  143. LM = IPERM(IJ)
  144. C
  145. C If first element of array is greater than LM, interchange with LM
  146. C
  147. IF (DX(IPERM(I)) .GT. DX(LM)) THEN
  148. IPERM(IJ) = IPERM(I)
  149. IPERM(I) = LM
  150. LM = IPERM(IJ)
  151. ENDIF
  152. L = J
  153. C
  154. C If last element of array is less than LM, interchange with LM
  155. C
  156. IF (DX(IPERM(J)) .LT. DX(LM)) THEN
  157. IPERM(IJ) = IPERM(J)
  158. IPERM(J) = LM
  159. LM = IPERM(IJ)
  160. C
  161. C If first element of array is greater than LM, interchange
  162. C with LM
  163. C
  164. IF (DX(IPERM(I)) .GT. DX(LM)) THEN
  165. IPERM(IJ) = IPERM(I)
  166. IPERM(I) = LM
  167. LM = IPERM(IJ)
  168. ENDIF
  169. ENDIF
  170. GO TO 60
  171. 50 LMT = IPERM(L)
  172. IPERM(L) = IPERM(K)
  173. IPERM(K) = LMT
  174. C
  175. C Find an element in the second half of the array which is smaller
  176. C than LM
  177. C
  178. 60 L = L-1
  179. IF (DX(IPERM(L)) .GT. DX(LM)) GO TO 60
  180. C
  181. C Find an element in the first half of the array which is greater
  182. C than LM
  183. C
  184. 70 K = K+1
  185. IF (DX(IPERM(K)) .LT. DX(LM)) GO TO 70
  186. C
  187. C Interchange these elements
  188. C
  189. IF (K .LE. L) GO TO 50
  190. C
  191. C Save upper and lower subscripts of the array yet to be sorted
  192. C
  193. IF (L-I .GT. J-K) THEN
  194. IL(M) = I
  195. IU(M) = L
  196. I = K
  197. M = M+1
  198. ELSE
  199. IL(M) = K
  200. IU(M) = J
  201. J = L
  202. M = M+1
  203. ENDIF
  204. GO TO 90
  205. C
  206. C Begin again on another portion of the unsorted array
  207. C
  208. 80 M = M-1
  209. IF (M .EQ. 0) GO TO 120
  210. I = IL(M)
  211. J = IU(M)
  212. C
  213. 90 IF (J-I .GE. 1) GO TO 40
  214. IF (I .EQ. 1) GO TO 30
  215. I = I-1
  216. C
  217. 100 I = I+1
  218. IF (I .EQ. J) GO TO 80
  219. LM = IPERM(I+1)
  220. IF (DX(IPERM(I)) .LE. DX(LM)) GO TO 100
  221. K = I
  222. C
  223. 110 IPERM(K+1) = IPERM(K)
  224. K = K-1
  225. IF (DX(LM) .LT. DX(IPERM(K))) GO TO 110
  226. IPERM(K+1) = LM
  227. GO TO 100
  228. C
  229. C Clean up
  230. C
  231. 120 IF (KFLAG .LE. -1) THEN
  232. DO 130 I=1,NN
  233. DX(I) = -DX(I)
  234. 130 CONTINUE
  235. ENDIF
  236. C
  237. C Rearrange the values of DX if desired
  238. C
  239. IF (KK .EQ. 2) THEN
  240. C
  241. C Use the IPERM vector as a flag.
  242. C If IPERM(I) < 0, then the I-th value is in correct location
  243. C
  244. DO 150 ISTRT=1,NN
  245. IF (IPERM(ISTRT) .GE. 0) THEN
  246. INDX = ISTRT
  247. INDX0 = INDX
  248. TEMP = DX(ISTRT)
  249. 140 IF (IPERM(INDX) .GT. 0) THEN
  250. DX(INDX) = DX(IPERM(INDX))
  251. INDX0 = INDX
  252. IPERM(INDX) = -IPERM(INDX)
  253. INDX = ABS(IPERM(INDX))
  254. GO TO 140
  255. ENDIF
  256. DX(INDX0) = TEMP
  257. ENDIF
  258. 150 CONTINUE
  259. C
  260. C Revert the signs of the IPERM values
  261. C
  262. DO 160 I=1,NN
  263. IPERM(I) = -IPERM(I)
  264. 160 CONTINUE
  265. C
  266. ENDIF
  267. C
  268. RETURN
  269. END