Changeset 13870
- Timestamp:
- 02/11/12 15:53:33 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/abcl/src/org/armedbear/lisp/sort.lisp
r13852 r13870 34 34 (require "EXTENSIBLE-SEQUENCES-BASE") 35 35 36 (defun sort (sequence predicate &rest args &key key) 37 (sequence::seq-dispatch sequence 38 (sort-list sequence predicate key) 39 (quicksort sequence 0 (1- (length sequence)) predicate (or key #'identity)) 40 (apply #'sequence:sort sequence predicate args))) 41 42 (defun stable-sort (sequence predicate &rest args &key key) 43 (sequence::seq-dispatch sequence 44 (sort-list sequence predicate key) 45 ;;; Jorge Tavares: 46 ;;; As a quick fix, I send in attach a patch that uses in stable-sort merge 47 ;;; sort for all sequences. This is done by coercing the sequence to list, 48 ;;; calling merge sort and coercing it back to the original sequence type. 49 ;;; However, as a long term improvement, the best solution would be to 50 ;;; implement a merge sort for non-list sequences. 51 (coerce (sort-list (coerce sequence 'list) 52 predicate 53 key) 54 (type-of sequence)) 55 (apply #'sequence:stable-sort sequence predicate args))) 36 ;;; 37 ;;; STABLE SORT 38 ;;; 39 40 ;;; 41 ;;; MERGE SORT for vectors (and sequences in general) 42 ;;; 43 ;;; - top-down stable merge sort 44 ;;; - it is defined with 2 macros to allow a single algorithm 45 ;;; and multiple sequence types: merge-vectors-body and merge-sort-body 46 ;;; - merge-vectors-body merges two given sequences 47 ;;; - merge-sort-body contains the top-down algorithm 48 ;;; - the body macro is called by the merge-sort-vectors functions, 49 ;;; which typecases the type of sequence and expands the apropriate body 50 ;;; - more types of sequences/vectors can be added 51 ;;; - the macros generate the merge sort body with or without funcall to key 52 ;;; - the merge-vectors algorithm is inspired from the CCL base code 53 ;;; 54 55 (defmacro merge-vectors-body (type ref a start-a end-a b start-b end-b aux start-aux predicate &optional key) 56 (let ((i-a (gensym)) 57 (i-b (gensym)) 58 (i-aux (gensym)) 59 (v-a (gensym)) 60 (v-b (gensym)) 61 (k-a (gensym)) 62 (k-b (gensym)) 63 (merge-block (gensym))) 64 `(locally 65 (declare (type fixnum ,start-a ,end-a ,start-b ,end-b ,start-aux) 66 (type ,type ,a ,b) 67 (type simple-vector ,aux) 68 (type function ,predicate ,@(if key `(,key))) 69 (optimize (speed 3) (safety 0))) 70 (block ,merge-block 71 (let ((,i-a ,start-a) 72 (,i-b ,start-b) 73 (,i-aux ,start-aux) 74 ,v-a ,v-b ,k-a ,k-b) 75 (declare (type fixnum ,i-a ,i-b ,i-aux)) 76 (cond ((= ,start-a ,end-a) 77 (when (= ,start-b ,end-b) 78 (return-from ,merge-block)) 79 (setf ,i-a ,start-b 80 ,end-a ,end-b 81 ,a ,b 82 ,v-a (,ref ,a ,i-a))) 83 ((= ,start-b ,end-b) 84 (setf ,i-a ,start-a 85 ,v-a (,ref ,a ,i-a))) 86 (t 87 (setf ,v-a (,ref ,a ,i-a) 88 ,v-b (,ref ,b ,i-b) 89 ,@(if key 90 `(,k-a (funcall ,key ,v-a)) 91 `(,k-a ,v-a)) 92 ,@(if key 93 `(,k-b (funcall ,key ,v-b)) 94 `(,k-b ,v-b))) 95 (loop 96 (if (funcall ,predicate ,k-b ,k-a) 97 (progn 98 (setf (svref ,aux ,i-aux) ,v-b 99 ,i-aux (+ ,i-aux 1) 100 ,i-b (+ ,i-b 1)) 101 (when (= ,i-b ,end-b) (return)) 102 (setf ,v-b (,ref ,b ,i-b) 103 ,@(if key 104 `(,k-b (funcall ,key ,v-b)) 105 `(,k-b ,v-b)))) 106 (progn 107 (setf (svref ,aux ,i-aux) ,v-a 108 ,i-aux (+ ,i-aux 1) 109 ,i-a (+ ,i-a 1)) 110 (when (= ,i-a ,end-a) 111 (setf ,a ,b 112 ,i-a ,i-b 113 ,end-a ,end-b 114 ,v-a ,v-b) 115 (return)) 116 (setf ,v-a (,ref ,a ,i-a) 117 ,@(if key 118 `(,k-a (funcall ,key ,v-a)) 119 `(,k-a ,v-a)))))))) 120 (loop 121 (setf (svref ,aux ,i-aux) ,v-a 122 ,i-a (+ ,i-a 1)) 123 (when (= ,i-a ,end-a) (return)) 124 (setf ,v-a (,ref ,a ,i-a) 125 ,i-aux (+ ,i-aux 1)))))))) 126 127 (defmacro merge-sort-body (type ref mpredicate mkey msequence mstart mend) 128 (let ((merge-sort-call (gensym)) 129 (maux (gensym)) 130 (aux (gensym)) 131 (sequence (gensym)) 132 (start (gensym)) 133 (end (gensym)) 134 (predicate (gensym)) 135 (key (gensym)) 136 (mid (gensym)) 137 (direction (gensym))) 138 `(locally 139 (declare (optimize (speed 3) (safety 0))) 140 (labels ((,merge-sort-call (,sequence ,start ,end ,predicate ,key ,aux ,direction) 141 (declare (type function ,predicate ,@(if mkey `(,key))) 142 (type fixnum ,start ,end) 143 (type ,type ,sequence)) 144 (let ((,mid (+ ,start (ash (- ,end ,start) -1)))) 145 (declare (type fixnum ,mid)) 146 (if (<= (- ,mid 1) ,start) 147 (unless ,direction (setf (,ref ,aux ,start) (,ref ,sequence ,start))) 148 (,merge-sort-call ,sequence ,start ,mid ,predicate ,key ,aux (not ,direction))) 149 (if (>= (+ ,mid 1) ,end) 150 (unless ,direction (setf (,ref ,aux ,mid) (,ref ,sequence ,mid))) 151 (,merge-sort-call ,sequence ,mid ,end ,predicate ,key ,aux (not ,direction))) 152 (unless ,direction (psetq ,sequence ,aux ,aux ,sequence)) 153 ,(if mkey 154 `(merge-vectors-body ,type ,ref ,sequence ,start ,mid ,sequence 155 ,mid ,end ,aux ,start ,predicate ,key) 156 `(merge-vectors-body ,type ,ref ,sequence ,start ,mid ,sequence 157 ,mid ,end ,aux ,start ,predicate))))) 158 (let ((,maux (make-array ,mend))) 159 (declare (type simple-vector ,maux)) 160 (,merge-sort-call ,msequence ,mstart ,mend ,mpredicate ,mkey ,maux nil)))))) 161 162 (defun merge-sort-vectors (sequence predicate key) 163 (let ((end (length sequence))) 164 (typecase sequence 165 (simple-vector 166 (if key 167 (merge-sort-body simple-vector svref predicate key sequence 0 end) 168 (merge-sort-body simple-vector svref predicate nil sequence 0 end))) 169 (vector 170 (if key 171 (merge-sort-body vector aref predicate key sequence 0 end) 172 (merge-sort-body vector aref predicate nil sequence 0 end)))) 173 sequence)) 174 175 176 ;;; 177 ;;; MERGE SORT for lists 178 ;;; 56 179 57 180 ;; Adapted from SBCL. … … 183 306 (return list-1)))))) 184 307 185 #| 186 <> dc:author "Jorge Tavares" ; 187 dc:description 188 """ 189 The quicksort function picks the pivot by selecting a midpoint and 190 also sorts the smaller partition first. These are enough to avoid the 191 stack overflow problem as reported. I've performed some tests and it 192 looks it is correct 193 """" . 194 |# 308 309 ;;; 310 ;;; SORT 311 ;;; 312 195 313 ;;; 196 314 ;;; QUICKSORT 197 ;;; - the pivot is a middle point 315 ;;; 316 ;;; - algorithm is in the quicksort-body macro, so that it allows 317 ;;; the use of different types (e.g., simple-vector, vector) 318 ;;; - the pivot is picked by selecting middle point 198 319 ;;; - sorts the smaller partition first 199 ;;; 200 (defun quicksort (vector start end predicate key) 201 (declare (type fixnum start end) 202 (type function predicate key))203 ( if (< start end)204 (let* ((i start)205 (j (1+ end))206 (p (+ start (ash (- end start) -1)))207 (d (aref vector p))208 (kd (funcall key d)))209 ( rotatef (aref vector p) (aref vector start))210 ( block outer-loop211 (loop212 (loop213 (unless (> (decf j) i) (return-from outer-loop))214 (when (funcall predicate215 (funcall key (aref vector j)) kd)216 (return)))217 (loop218 (unless (< (incf i) j) (return-from outer-loop))219 (unless (funcall predicate220 (funcall key (aref vector i)) kd)221 (return)))222 (rotatef (aref vector i) (aref vector j))))223 (setf (aref vector start) (aref vector j)224 (aref vector j) d)225 (if (< (- j start) (- end j))226 (progn227 (quicksort vector start (1- j) predicate key)228 (quicksort vector (1+ j) end predicate key))229 (progn230 (quicksort vector (1+ j) end predicate key)231 (quicksort vector start (1- j) predicate key))))232 vector))233 234 ;;; DEPRECATED -- to be removed in abcl-1.4 235 ;;; From ECL. 236 (defun quick-sort (seq start end pred key)237 (unless key (setq key #'identity))238 (if (<= end (1+ start)) 239 seq 240 (let* ((j start) (k end) (d (elt seq start)) (kd (funcall key d))) 241 (block outer-loop 242 (loop (loop (decf k)243 (unless (< j k) (return-from outer-loop))244 (when (funcall pred (funcall key (elt seq k)) kd)245 (return)))246 (loop (incfj)247 (unless (< j k) (return-from outer-loop))248 (unless (funcall pred (funcall key (elt seq j)) kd)249 (return))) 250 (let ((temp (elt seq j)))251 (setf (elt seq j) (elt seq k)252 (elt seq k) temp)))) 253 (setf (elt seq start) (elt seq j)254 (elt seq j) d)255 (quick-sort seq start j pred key)256 (quick-sort seq (1+ j) end pred key)))) 257 258 ;;; From ECL. Should already be user-extensible as it does no type dispatch 259 ;;; and uses only user-extensible functions. 260 (defun merge (result-type sequence1 sequence2 predicate 261 &keykey262 &aux (l1 (length sequence1)) (l2 (length sequence2)))263 (unless key (setq key #'identity))264 (do ((newseq (make-sequence result-type (+ l1 l2)))265 ( j 0 (1+ j))266 (i1 0)267 (i2 0))268 ((and (= i1 l1) (= i2 l2)) newseq)269 (cond ((and (< i1 l1) (< i2 l2)) 270 (cond ((funcall predicate 271 (funcall key (elt sequence1 i1)) 272 (funcall key (elt sequence2 i2))) 273 (setf (elt newseq j) (elt sequence1 i1)) 274 (incf i1))275 ((funcall predicate 276 (funcall key (elt sequence2 i2)) 277 (funcall key (elt sequence1 i1))) 278 (setf (elt newseq j) (elt sequence2 i2))279 (incf i2))280 (t281 (setf (elt newseq j) (elt sequence1 i1))282 (incf i1))))283 ((< i1 l1) 284 (setf (elt newseq j) (elt sequence1 i1))285 (incf i1))286 (t287 (setf (elt newseq j) (elt sequence2 i2))288 (incf i2)))))320 ;;; - the macro generates the quicksort body with or without funcall to key 321 ;;; 322 323 (defmacro quicksort-body (type ref mpredicate mkey sequence mstart mend) 324 (let ((quicksort-call (gensym)) 325 (predicate (gensym)) 326 (key (gensym)) 327 (vector (gensym)) 328 (start (gensym)) 329 (end (gensym)) 330 (i (gensym)) 331 (j (gensym)) 332 (p (gensym)) 333 (d (gensym)) 334 (kd (gensym))) 335 `(locally 336 (declare (speed 3) (safety 0)) 337 (labels ((,quicksort-call (,vector ,start ,end ,predicate ,key) 338 (declare (type function ,predicate ,@(if mkey `(,key))) 339 (type fixnum ,start ,end) 340 (type ,type ,sequence)) 341 (if (< ,start ,end) 342 (let* ((,i ,start) 343 (,j (1+ ,end)) 344 (,p (the fixnum (+ ,start (ash (- ,end ,start) -1)))) 345 (,d (,ref ,vector ,p)) 346 ,@(if mkey 347 `((,kd (funcall ,key ,d))) 348 `((,kd ,d)))) 349 (rotatef (,ref ,vector ,p) (,ref ,vector ,start)) 350 (block outer-loop 351 (loop 352 (loop 353 (unless (> (decf ,j) ,i) (return-from outer-loop)) 354 (when (funcall ,predicate 355 ,@(if mkey 356 `((funcall ,key (,ref ,vector ,j))) 357 `((,ref ,vector ,j))) 358 ,kd) (return))) 359 (loop 360 (unless (< (incf ,i) ,j) (return-from outer-loop)) 361 (unless (funcall ,predicate 362 ,@(if mkey 363 `((funcall ,key (,ref ,vector ,i))) 364 `((,ref ,vector ,i))) 365 ,kd) (return))) 366 (rotatef (,ref ,vector ,i) (,ref ,vector ,j)))) 367 (setf (,ref ,vector ,start) (,ref ,vector ,j) 368 (,ref ,vector ,j) ,d) 369 (if (< (- ,j ,start) (- ,end ,j)) 370 (progn 371 (,quicksort-call ,vector ,start (1- ,j) ,predicate ,key) 372 (,quicksort-call ,vector (1+ ,j) ,end ,predicate ,key)) 373 (progn 374 (,quicksort-call ,vector (1+ ,j) ,end ,predicate ,key) 375 (,quicksort-call ,vector ,start (1- ,j) ,predicate ,key))))))) 376 (,quicksort-call ,sequence ,mstart ,mend ,mpredicate ,mkey))))) 377 378 (defun quicksort (sequence predicate key) 379 (let ((end (1- (length sequence)))) 380 (typecase sequence 381 (simple-vector 382 (if key 383 (quicksort-body simple-vector svref predicate key sequence 0 end) 384 (quicksort-body simple-vector svref predicate nil sequence 0 end))) 385 (vector 386 (if key 387 (quicksort-body vector aref predicate key sequence 0 end) 388 (quicksort-body vector aref predicate nil sequence 0 end)))) 389 sequence)) 390 391 392 ;;; 393 ;;; main SORT and STABLE-SORT function calls 394 ;;; 395 ;;; - sort: quicksort and merge sort (only for lists) 396 ;;; - stable-sort: merge sort (all types) 397 ;;; 398 399 (defun sort (sequence predicate &rest args &key key) 400 (sequence::seq-dispatch sequence 401 (sort-list sequence predicate key) 402 (quicksort sequence predicate key) 403 (apply #'sequence:sort sequence predicate args))) 404 405 (defun stable-sort (sequence predicate &rest args &key key) 406 (sequence::seq-dispatch sequence 407 (sort-list sequence predicate key) 408 (merge-sort-vectors sequence predicate key) 409 (apply #'sequence:stable-sort sequence predicate args)))
Note: See TracChangeset
for help on using the changeset viewer.