home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / src-16f.lha / code / sort.lisp < prev    next >
Encoding:
Text File  |  1992-05-30  |  15.7 KB  |  447 lines

  1. ;;; -*- Log: code.log; Package: Lisp -*-
  2. ;;;
  3. ;;; **********************************************************************
  4. ;;; This code was written as part of the CMU Common Lisp project at
  5. ;;; Carnegie Mellon University, and has been placed in the public domain.
  6. ;;; If you want to use this code or any part of CMU Common Lisp, please contact
  7. ;;; Scott Fahlman or slisp-group@cs.cmu.edu.
  8. ;;;
  9. (ext:file-comment
  10.   "$Header: sort.lisp,v 1.2 91/02/08 13:35:46 ram Exp $")
  11. ;;;
  12. ;;; **********************************************************************
  13. ;;;
  14. ;;; Sort functions for Spice Lisp 
  15. ;;;   these functions are part of the standard spice lisp environment.  
  16. ;;; 
  17. ;;; Written by Jim Large 
  18. ;;; Hacked on and maintained by Skef Wholey 
  19. ;;; Rewritten by Bill Chiles
  20. ;;;
  21. ;;; *******************************************************************
  22.  
  23. (in-package 'lisp)
  24.  
  25. (export '(sort stable-sort merge))
  26.  
  27.  
  28.  
  29. (defun sort (sequence predicate &key key)
  30.   "Destructively sorts sequence.  Predicate should returns non-Nil if
  31.    Arg1 is to precede Arg2."
  32.   (typecase sequence
  33.     (simple-vector
  34.      (if (> (the fixnum (length (the simple-vector sequence))) 0)
  35.      (sort-simple-vector sequence predicate key)
  36.      sequence))
  37.     (list
  38.      (sort-list sequence predicate key))
  39.     (vector
  40.      (if (> (the fixnum (length sequence)) 0)
  41.      (sort-vector sequence predicate key)
  42.      sequence))
  43.     (t
  44.      (error "~S is not a sequence." sequence))))
  45.  
  46.  
  47.  
  48. ;;; Sorting Vectors
  49.  
  50. ;;; Sorting is done with a heap sort.
  51.  
  52. (eval-when (compile eval)
  53.  
  54. ;;; HEAPIFY, assuming both sons of root are heaps, percolates the root element
  55. ;;; through the sons to form a heap at root.  Root and max are zero based
  56. ;;; coordinates, but the heap algorithm only works on arrays indexed from 1
  57. ;;; through N (not 0 through N-1); This is because a root at I has sons at 2*I
  58. ;;; and 2*I+1 which does not work for a root at 0.  Because of this, boundaries,
  59. ;;; roots, and termination are computed using 1..N indexes.
  60.  
  61. (defmacro heapify (seq vector-ref root max pred key)
  62.   (let ((heap-root (gensym))   (heap-max (gensym))     (root-ele (gensym))
  63.     (root-key (gensym))    (heap-max/2 (gensym))   (heap-l-son (gensym))
  64.     (one-son (gensym))     (one-son-ele (gensym))  (one-son-key (gensym))
  65.     (r-son-ele (gensym))   (r-son-key (gensym))    (var-root (gensym)))
  66.     `(let* ((,var-root ,root) ; necessary to not clobber calling root var.
  67.         (,heap-root (1+ ,root))
  68.         (,heap-max (1+ ,max))
  69.         (,root-ele (,vector-ref ,seq ,root))
  70.         (,root-key (apply-key ,key ,root-ele))
  71.         (,heap-max/2 (ash ,heap-max -1))) ; (floor heap-max 2)
  72.        (declare (fixnum ,var-root ,heap-root ,heap-max ,heap-max/2))
  73.        (loop
  74.     (if (> ,heap-root ,heap-max/2) (return))
  75.     (let* ((,heap-l-son (ash ,heap-root 1)) ; (* 2 heap-root)
  76.            ;; l-son index in seq (0..N-1) is one less than heap computation
  77.            (,one-son (1- ,heap-l-son))
  78.            (,one-son-ele (,vector-ref ,seq ,one-son))
  79.            (,one-son-key (apply-key ,key ,one-son-ele)))
  80.       (declare (fixnum ,heap-l-son ,one-son))
  81.       (if (< ,heap-l-son ,heap-max)
  82.           ;; there is a right son.
  83.           (let* ((,r-son-ele (,vector-ref ,seq ,heap-l-son))
  84.              (,r-son-key (apply-key ,key ,r-son-ele)))
  85.         ;; choose the greater of the two sons.
  86.         (when (funcall ,pred ,one-son-key ,r-son-key)
  87.           (setf ,one-son ,heap-l-son)
  88.           (setf ,one-son-ele ,r-son-ele)
  89.           (setf ,one-son-key ,r-son-key))))
  90.       ;; if greater son is less than root, then we've formed a heap again.
  91.       (if (funcall ,pred ,one-son-key ,root-key) (return))
  92.       ;; else put greater son at root and make greater son node be the root.
  93.       (setf (,vector-ref ,seq ,var-root) ,one-son-ele)
  94.       (setf ,heap-root (1+ ,one-son)) ; one plus to be in heap coordinates.
  95.       (setf ,var-root ,one-son)))     ; actual index into vector for root ele.
  96.        ;; now really put percolated value into heap at the appropriate root node.
  97.        (setf (,vector-ref ,seq ,var-root) ,root-ele))))
  98.  
  99.  
  100. ;;; BUILD-HEAP rearranges seq elements into a heap to start heap sorting.
  101. (defmacro build-heap (seq type len-1 pred key)
  102.   (let ((i (gensym)))
  103.     `(do ((,i (floor ,len-1 2) (1- ,i)))
  104.      ((minusp ,i) ,seq)
  105.        (declare (fixnum ,i))
  106.        (heapify ,seq ,type ,i ,len-1 ,pred ,key))))
  107.  
  108. ) ; eval-when
  109.  
  110.  
  111. ;;; Make simple-vector and miscellaneous vector sorting functions.
  112. (macrolet ((frob-rob (fun-name vector-ref)
  113.          `(defun ,fun-name (seq pred key)
  114.         (let ((len-1 (1- (length (the vector seq)))))
  115.           (declare (fixnum len-1))
  116.           (build-heap seq ,vector-ref len-1 pred key)
  117.           (do* ((i len-1 i-1)
  118.             (i-1 (1- i) (1- i-1)))
  119.                ((zerop i) seq)
  120.             (declare (fixnum i i-1))
  121.             (rotatef (,vector-ref seq 0) (,vector-ref seq i))
  122.             (heapify seq ,vector-ref 0 i-1 pred key))))))
  123.  
  124.   (frob-rob sort-vector aref)
  125.  
  126.   (frob-rob sort-simple-vector svref))
  127.  
  128.  
  129.  
  130. ;;;; Stable Sorting
  131.  
  132. (defun stable-sort (sequence predicate &key key)
  133.   "Destructively sorts sequence.  Predicate should returns non-Nil if
  134.    Arg1 is to precede Arg2."
  135.   (typecase sequence
  136.     (simple-vector
  137.      (stable-sort-simple-vector sequence predicate key))
  138.     (list
  139.      (sort-list sequence predicate key))
  140.     (vector
  141.      (stable-sort-vector sequence predicate key))
  142.     (t
  143.      (error "~S is not a sequence." sequence))))
  144.  
  145.  
  146. ;;; Stable Sorting Lists
  147.  
  148.  
  149. ;;; SORT-LIST uses a bottom up merge sort.  First a pass is made over
  150. ;;; the list grabbing one element at a time and merging it with the next one
  151. ;;; form pairs of sorted elements.  Then n is doubled, and elements are taken
  152. ;;; in runs of two, merging one run with the next to form quadruples of sorted
  153. ;;; elements.  This continues until n is large enough that the inner loop only
  154. ;;; runs for one iteration; that is, there are only two runs that can be merged,
  155. ;;; the first run starting at the beginning of the list, and the second being
  156. ;;; the remaining elements.
  157.  
  158. (defun sort-list (list pred key)
  159.   (let ((head (cons :header list))  ; head holds on to everything
  160.     (n 1)                       ; bottom-up size of lists to be merged
  161.     unsorted            ; unsorted is the remaining list to be
  162.                     ;   broken into n size lists and merged
  163.     list-1                ; list-1 is one length n list to be merged
  164.     last)                ; last points to the last visited cell
  165.     (declare (fixnum n))
  166.     (loop
  167.      ;; start collecting runs of n at the first element
  168.      (setf unsorted (cdr head))
  169.      ;; tack on the first merge of two n-runs to the head holder
  170.      (setf last head)
  171.      (let ((n-1 (1- n)))
  172.        (declare (fixnum n-1))
  173.        (loop
  174.     (setf list-1 unsorted)
  175.     (let ((temp (nthcdr n-1 list-1))
  176.           list-2)
  177.       (cond (temp
  178.          ;; there are enough elements for a second run
  179.          (setf list-2 (cdr temp))
  180.          (setf (cdr temp) nil)
  181.          (setf temp (nthcdr n-1 list-2))
  182.          (cond (temp
  183.             (setf unsorted (cdr temp))
  184.             (setf (cdr temp) nil))
  185.                ;; the second run goes off the end of the list
  186.                (t (setf unsorted nil)))
  187.          (multiple-value-bind (merged-head merged-last)
  188.                       (merge-lists* list-1 list-2 pred key)
  189.            (setf (cdr last) merged-head)
  190.            (setf last merged-last))
  191.          (if (null unsorted) (return)))
  192.         ;; if there is only one run, then tack it on to the end
  193.         (t (setf (cdr last) list-1)
  194.            (return)))))
  195.        (setf n (ash n 1)) ; (+ n n)
  196.        ;; If the inner loop only executed once, then there were only enough
  197.        ;; elements for two runs given n, so all the elements have been merged
  198.        ;; into one list.  This may waste one outer iteration to realize.
  199.        (if (eq list-1 (cdr head))
  200.        (return list-1))))))
  201.  
  202.  
  203. ;;; APPLY-PRED saves us a function call sometimes.
  204. (eval-when (compile eval)
  205.   (defmacro apply-pred (one two pred key)
  206.     `(if ,key
  207.      (funcall ,pred (funcall ,key ,one)
  208.           (funcall ,key  ,two))
  209.      (funcall ,pred ,one ,two)))
  210. ) ; eval-when
  211.  
  212. (defvar *merge-lists-header* (list :header))
  213.  
  214. ;;; MERGE-LISTS*   originally written by Jim Large.
  215. ;;;            modified to return a pointer to the end of the result
  216. ;;;               and to not cons header each time its called.
  217. ;;; It destructively merges list-1 with list-2.  In the resulting
  218. ;;; list, elements of list-2 are guaranteed to come after equal elements
  219. ;;; of list-1.
  220. (defun merge-lists* (list-1 list-2 pred key)
  221.   (do* ((result *merge-lists-header*)
  222.     (P result))                            ; P points to last cell of result
  223.        ((or (null list-1) (null list-2))       ; done when either list used up    
  224.     (if (null list-1)                      ; in which case, append the
  225.         (rplacd p list-2)                  ;   other list
  226.         (rplacd p list-1))
  227.     (do ((drag p lead)
  228.          (lead (cdr p) (cdr lead)))
  229.         ((null lead)
  230.          (values (prog1 (cdr result)       ; return the result sans header
  231.                 (rplacd result nil)) ; (free memory, be careful)
  232.              drag))))               ; and return pointer to last element
  233.     (cond ((apply-pred (car list-2) (car list-1) pred key)
  234.        (rplacd p list-2)           ; append the lesser list to last cell of
  235.        (setq p (cdr p))            ;   result.  Note: test must bo done for
  236.        (pop list-2))               ;   list-2 < list-1 so merge will be
  237.       (T (rplacd p list-1)         ;   stable for list-1
  238.          (setq p (cdr p))
  239.          (pop list-1)))))
  240.  
  241.  
  242.  
  243. ;;; Stable Sort Vectors
  244.  
  245. ;;; Stable sorting vectors is done with the same algorithm used for lists,
  246. ;;; using a temporary vector to merge back and forth between it and the
  247. ;;; given vector to sort.
  248.  
  249.  
  250. (eval-when (compile eval)
  251.  
  252. ;;; STABLE-SORT-MERGE-VECTORS* takes a source vector with subsequences,
  253. ;;;    start-1 (inclusive) ... end-1 (exclusive) and
  254. ;;;    end-1 (inclusive) ... end-2 (exclusive),
  255. ;;; and merges them into a target vector starting at index start-1.
  256.  
  257. (defmacro stable-sort-merge-vectors* (source target start-1 end-1 end-2
  258.                          pred key source-ref target-ref)
  259.   (let ((i (gensym))
  260.     (j (gensym))
  261.     (target-i (gensym)))
  262.     `(let ((,i ,start-1)
  263.        (,j ,end-1) ; start-2
  264.        (,target-i ,start-1))
  265.        (declare (fixnum ,i ,j ,target-i))
  266.        (loop
  267.     (cond ((= ,i ,end-1)
  268.            (loop (if (= ,j ,end-2) (return))
  269.              (setf (,target-ref ,target ,target-i)
  270.                (,source-ref ,source ,j))
  271.              (incf ,target-i)
  272.              (incf ,j))
  273.            (return))
  274.           ((= ,j ,end-2)
  275.            (loop (if (= ,i ,end-1) (return))
  276.              (setf (,target-ref ,target ,target-i)
  277.                (,source-ref ,source ,i))
  278.              (incf ,target-i)
  279.              (incf ,i))
  280.            (return))
  281.           ((apply-pred (,source-ref ,source ,j)
  282.                (,source-ref ,source ,i)
  283.                ,pred ,key)
  284.            (setf (,target-ref ,target ,target-i)
  285.              (,source-ref ,source ,j))
  286.            (incf ,j))
  287.           (t (setf (,target-ref ,target ,target-i)
  288.                (,source-ref ,source ,i))
  289.          (incf ,i)))
  290.     (incf ,target-i)))))
  291.  
  292.  
  293. ;;; VECTOR-MERGE-SORT is the same algorithm used to stable sort lists, but
  294. ;;; it uses a temporary vector.  Direction determines whether we are merging
  295. ;;; into the temporary (T) or back into the given vector (NIL).
  296.  
  297. (defmacro vector-merge-sort (vector pred key vector-ref)
  298.   (let ((vector-len (gensym))         (n (gensym))
  299.     (direction (gensym))         (unsorted (gensym))
  300.     (start-1 (gensym))         (end-1 (gensym))
  301.     (end-2 (gensym))         (temp-len (gensym))
  302.     (i (gensym)))
  303.     `(let ((,vector-len (length (the vector ,vector)))
  304.        (,n 1)         ; bottom-up size of contiguous runs to be merged
  305.        (,direction t) ; t vector --> temp    nil temp --> vector
  306.        (,temp-len (length (the simple-vector *merge-sort-temp-vector*)))
  307.        (,unsorted 0)  ; unsorted..vector-len are the elements that need
  308.               ; to be merged for a given n
  309.        (,start-1 0))  ; one n-len subsequence to be merged with the next
  310.        (declare (fixnum ,vector-len ,n ,temp-len ,unsorted ,start-1))
  311.        (if (> ,vector-len ,temp-len)
  312.        (setf *merge-sort-temp-vector*
  313.          (make-array (max ,vector-len (+ ,temp-len ,temp-len)))))
  314.        (loop
  315.     ;; for each n, we start taking n-runs from the start of the vector
  316.     (setf ,unsorted 0)
  317.     (loop
  318.      (setf ,start-1 ,unsorted)
  319.      (let ((,end-1 (+ ,start-1 ,n)))
  320.        (declare (fixnum ,end-1))
  321.        (cond ((< ,end-1 ,vector-len)
  322.           ;; there are enough elements for a second run
  323.           (let ((,end-2 (+ ,end-1 ,n)))
  324.             (declare (fixnum ,end-2))
  325.             (if (> ,end-2 ,vector-len) (setf ,end-2 ,vector-len))
  326.             (setf ,unsorted ,end-2)
  327.             (if ,direction
  328.             (stable-sort-merge-vectors*
  329.              ,vector *merge-sort-temp-vector*
  330.              ,start-1 ,end-1 ,end-2 ,pred ,key ,vector-ref svref)
  331.             (stable-sort-merge-vectors*
  332.              *merge-sort-temp-vector* ,vector
  333.              ,start-1 ,end-1 ,end-2 ,pred ,key svref ,vector-ref))
  334.             (if (= ,unsorted ,vector-len) (return))))
  335.          ;; if there is only one run, copy those elements to the end
  336.          (t (if ,direction
  337.             (do ((,i ,start-1 (1+ ,i)))
  338.                 ((= ,i ,vector-len))
  339.               (declare (fixnum ,i))
  340.               (setf (svref *merge-sort-temp-vector* ,i)
  341.                 (,vector-ref ,vector ,i)))
  342.             (do ((,i ,start-1 (1+ ,i)))
  343.                 ((= ,i ,vector-len))
  344.               (declare (fixnum ,i))
  345.               (setf (,vector-ref ,vector ,i)
  346.                 (svref *merge-sort-temp-vector* ,i))))
  347.             (return)))))
  348.     ;; If the inner loop only executed once, then there were only enough
  349.     ;; elements for two subsequences given n, so all the elements have
  350.     ;; been merged into one list.  Start-1 will have remained 0 upon exit.
  351.     (when (zerop ,start-1)
  352.       (if ,direction
  353.           ;; if we just merged into the temporary, copy it all back
  354.           ;; to the given vector.
  355.           (dotimes (,i ,vector-len)
  356.         (setf (,vector-ref ,vector ,i)
  357.               (svref *merge-sort-temp-vector* ,i))))
  358.       (return ,vector))
  359.     (setf ,n (ash ,n 1)) ; (* 2 n)
  360.     (setf ,direction (not ,direction))))))
  361.  
  362. ) ; eval-when
  363.  
  364.  
  365. ;;; Temporary vector for stable sorting vectors.
  366. (defvar *merge-sort-temp-vector*
  367.   (make-array 50))
  368.  
  369. (proclaim '(simple-vector *merge-sort-temp-vector*))
  370.  
  371. (defun stable-sort-simple-vector (vector pred key)
  372.   (declare (simple-vector vector))
  373.   (vector-merge-sort vector pred key svref))
  374.  
  375. (defun stable-sort-vector (vector pred key)
  376.   (vector-merge-sort vector pred key aref))
  377.  
  378.  
  379.  
  380. ;;;; Merge
  381.  
  382. (eval-when (compile eval)
  383.  
  384. ;;; MERGE-VECTORS returns a new vector which contains an interleaving
  385. ;;; of the elements of vector-1 and vector-2.  Elements from vector-2 are
  386. ;;; chosen only if they are strictly less than elements of vector-1,
  387. ;;; (pred elt-2 elt-1), as specified in the manual.
  388.  
  389. (defmacro merge-vectors (vector-1 length-1 vector-2 length-2
  390.              result-vector pred key access)
  391.   (let ((result-i (gensym))
  392.     (i (gensym))
  393.     (j (gensym)))
  394.     `(let* ((,result-i 0)
  395.         (,i 0)
  396.         (,j 0))
  397.        (declare (fixnum ,result-i ,i ,j))
  398.        (loop
  399.     (cond ((= ,i ,length-1)
  400.            (loop (if (= ,j ,length-2) (return))
  401.              (setf (,access ,result-vector ,result-i)
  402.                (,access ,vector-2 ,j))
  403.              (incf ,result-i)
  404.              (incf ,j))
  405.            (return ,result-vector))
  406.           ((= ,j ,length-2)
  407.            (loop (if (= ,i ,length-1) (return))
  408.              (setf (,access ,result-vector ,result-i)
  409.                (,access ,vector-1 ,i))
  410.              (incf ,result-i)
  411.              (incf ,i))
  412.            (return ,result-vector))
  413.           ((apply-pred (,access ,vector-2 ,j) (,access ,vector-1 ,i)
  414.                ,pred ,key)
  415.            (setf (,access ,result-vector ,result-i)
  416.              (,access ,vector-2 ,j))
  417.            (incf ,j))
  418.           (t (setf (,access ,result-vector ,result-i)
  419.                (,access ,vector-1 ,i))
  420.          (incf ,i)))
  421.     (incf ,result-i)))))
  422.  
  423. ) ; eval-when
  424.  
  425. (defun merge (result-type sequence1 sequence2 predicate &key key)
  426.   "The sequences Sequence1 and Sequence2 are destructively merged into
  427.    a sequence of type Result-Type using the Predicate to order the elements."
  428.   (if (eq result-type 'list)
  429.       (let ((result (merge-lists* (coerce sequence1 'list)
  430.                   (coerce sequence2 'list)
  431.                   predicate key)))
  432.     result)
  433.       (let* ((vector-1 (coerce sequence1 'vector))
  434.          (vector-2 (coerce sequence2 'vector))
  435.          (length-1 (length vector-1))
  436.          (length-2 (length vector-2))
  437.          (result (make-sequence-of-type result-type (+ length-1 length-2))))
  438.     (declare (vector vector-1 vector-2)
  439.          (fixnum length-1 length-2))
  440.     (if (and (simple-vector-p result)
  441.          (simple-vector-p vector-1)
  442.          (simple-vector-p vector-2))
  443.         (merge-vectors vector-1 length-1 vector-2 length-2
  444.                result predicate key svref)
  445.         (merge-vectors vector-1 length-1 vector-2 length-2
  446.                result predicate key aref)))))
  447.