ipsort.f 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. *DECK IPSORT
  2. SUBROUTINE IPSORT (IX, N, IPERM, KFLAG, IER)
  3. C***BEGIN PROLOGUE IPSORT
  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 N6A1A, N6A2A
  10. C***TYPE INTEGER (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 Kahaner, D. K., (NBS)
  14. C Rhoads, G. S., (NBS)
  15. C Wisniewski, J. A., (SNLA)
  16. C***DESCRIPTION
  17. C
  18. C IPSORT returns the permutation vector IPERM generated by sorting
  19. C the array IX and, optionally, rearranges the values in IX. IX may
  20. C be sorted in increasing or decreasing order. A slightly modified
  21. C quicksort algorithm is used.
  22. C
  23. C IPERM is such that IX(IPERM(I)) is the Ith value in the
  24. C rearrangement of IX. IPERM may be applied to another array by
  25. C calling IPPERM, SPPERM, DPPERM or HPPERM.
  26. C
  27. C The main difference between IPSORT and its active sorting equivalent
  28. C ISORT is that the data are referenced indirectly rather than
  29. C directly. Therefore, IPSORT should require approximately twice as
  30. C long to execute as ISORT. However, IPSORT is more general.
  31. C
  32. C Description of Parameters
  33. C IX - input/output -- integer array of values to be sorted.
  34. C If ABS(KFLAG) = 2, then the values in IX will be
  35. C rearranged on output; otherwise, they are unchanged.
  36. C N - input -- number of values in array IX to be sorted.
  37. C IPERM - output -- permutation array such that IPERM(I) is the
  38. C index of the value in the original order of the
  39. C IX array that is in the Ith location in the sorted
  40. C order.
  41. C KFLAG - input -- control parameter:
  42. C = 2 means return the permutation vector resulting from
  43. C sorting IX in increasing order and sort IX also.
  44. C = 1 means return the permutation vector resulting from
  45. C sorting IX in increasing order and do not sort IX.
  46. C = -1 means return the permutation vector resulting from
  47. C sorting IX in decreasing order and do not sort IX.
  48. C = -2 means return the permutation vector resulting from
  49. C sorting IX in decreasing order and sort IX also.
  50. C IER - output -- error indicator:
  51. C = 0 if no error,
  52. C = 1 if N is zero or negative,
  53. C = 2 if KFLAG is not 2, 1, -1, or -2.
  54. C***REFERENCES R. C. Singleton, Algorithm 347, An efficient algorithm
  55. C for sorting with minimal storage, Communications of
  56. C the ACM, 12, 3 (1969), pp. 185-187.
  57. C***ROUTINES CALLED XERMSG
  58. C***REVISION HISTORY (YYMMDD)
  59. C 761101 DATE WRITTEN
  60. C 761118 Modified by John A. Wisniewski to use the Singleton
  61. C quicksort algorithm.
  62. C 810801 Further modified by David K. Kahaner.
  63. C 870423 Modified by Gregory S. Rhoads for passive sorting with the
  64. C option for the rearrangement of the original data.
  65. C 890620 Algorithm for rearranging the data vector corrected by R.
  66. C Boisvert.
  67. C 890622 Prologue upgraded to Version 4.0 style by D. Lozier.
  68. C 891128 Error when KFLAG.LT.0 and N=1 corrected by R. Boisvert.
  69. C 920507 Modified by M. McClain to revise prologue text.
  70. C 920818 Declarations section rebuilt and code restructured to use
  71. C IF-THEN-ELSE-ENDIF. (SMR, WRB)
  72. C***END PROLOGUE IPSORT
  73. C .. Scalar Arguments ..
  74. INTEGER IER, KFLAG, N
  75. C .. Array Arguments ..
  76. INTEGER IPERM(*), IX(*)
  77. C .. Local Scalars ..
  78. REAL R
  79. INTEGER I, IJ, INDX, INDX0, ISTRT, ITEMP, J, K, KK, L, LM, LMT, M,
  80. + NN
  81. C .. Local Arrays ..
  82. INTEGER IL(21), IU(21)
  83. C .. External Subroutines ..
  84. EXTERNAL XERMSG
  85. C .. Intrinsic Functions ..
  86. INTRINSIC ABS, INT
  87. C***FIRST EXECUTABLE STATEMENT IPSORT
  88. IER = 0
  89. NN = N
  90. IF (NN .LT. 1) THEN
  91. IER = 1
  92. CALL XERMSG ('SLATEC', 'IPSORT',
  93. + 'The number of values to be sorted, N, is not positive.',
  94. + IER, 1)
  95. RETURN
  96. ENDIF
  97. KK = ABS(KFLAG)
  98. IF (KK.NE.1 .AND. KK.NE.2) THEN
  99. IER = 2
  100. CALL XERMSG ('SLATEC', 'IPSORT',
  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 IX to get decreasing order if needed
  117. C
  118. IF (KFLAG .LE. -1) THEN
  119. DO 20 I=1,NN
  120. IX(I) = -IX(I)
  121. 20 CONTINUE
  122. ENDIF
  123. C
  124. C Sort IX only
  125. C
  126. M = 1
  127. I = 1
  128. J = NN
  129. R = .375E0
  130. C
  131. 30 IF (I .EQ. J) GO TO 80
  132. IF (R .LE. 0.5898437E0) THEN
  133. R = R+3.90625E-2
  134. ELSE
  135. R = R-0.21875E0
  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 (IX(IPERM(I)) .GT. IX(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 (IX(IPERM(J)) .LT. IX(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 (IX(IPERM(I)) .GT. IX(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 (IX(IPERM(L)) .GT. IX(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 (IX(IPERM(K)) .LT. IX(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 (IX(IPERM(I)) .LE. IX(LM)) GO TO 100
  221. K = I
  222. C
  223. 110 IPERM(K+1) = IPERM(K)
  224. K = K-1
  225. C
  226. IF (IX(LM) .LT. IX(IPERM(K))) GO TO 110
  227. IPERM(K+1) = LM
  228. GO TO 100
  229. C
  230. C Clean up
  231. C
  232. 120 IF (KFLAG .LE. -1) THEN
  233. DO 130 I=1,NN
  234. IX(I) = -IX(I)
  235. 130 CONTINUE
  236. ENDIF
  237. C
  238. C Rearrange the values of IX if desired
  239. C
  240. IF (KK .EQ. 2) THEN
  241. C
  242. C Use the IPERM vector as a flag.
  243. C If IPERM(I) < 0, then the I-th value is in correct location
  244. C
  245. DO 150 ISTRT=1,NN
  246. IF (IPERM(ISTRT) .GE. 0) THEN
  247. INDX = ISTRT
  248. INDX0 = INDX
  249. ITEMP = IX(ISTRT)
  250. 140 IF (IPERM(INDX) .GT. 0) THEN
  251. IX(INDX) = IX(IPERM(INDX))
  252. INDX0 = INDX
  253. IPERM(INDX) = -IPERM(INDX)
  254. INDX = ABS(IPERM(INDX))
  255. GO TO 140
  256. ENDIF
  257. IX(INDX0) = ITEMP
  258. ENDIF
  259. 150 CONTINUE
  260. C
  261. C Revert the signs of the IPERM values
  262. C
  263. DO 160 I=1,NN
  264. IPERM(I) = -IPERM(I)
  265. 160 CONTINUE
  266. C
  267. ENDIF
  268. C
  269. RETURN
  270. END