[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/heap 17429ee 07/31: Version 0.12 of the predictive comp
From: |
Stefan Monnier |
Subject: |
[elpa] externals/heap 17429ee 07/31: Version 0.12 of the predictive completion package. |
Date: |
Mon, 14 Dec 2020 12:13:33 -0500 (EST) |
branch: externals/heap
commit 17429eed7ba3b07db88a7a90b61848c9e729c4cc
Author: Toby Cubitt <toby-predictive@dr-qubit.org>
Commit: tsc25 <tsc25@cantab.net>
Version 0.12 of the predictive completion package.
---
heap.el | 209 ++++++++++++++++++++++++++++++++++++++++++----------------------
1 file changed, 139 insertions(+), 70 deletions(-)
diff --git a/heap.el b/heap.el
index 17e5893..9b388f1 100644
--- a/heap.el
+++ b/heap.el
@@ -5,7 +5,7 @@
;; Copyright (C) 2004-2006 Toby Cubitt
;; Author: Toby Cubitt <toby-predictive@dr-qubit.org>
-;; Version: 0.1.4
+;; Version: 0.2
;; Keywords: heap, priority queue
;; URL: http://www.dr-qubit.org/emacs.php
@@ -47,6 +47,12 @@
;; second. To implement a min-heap, it should return non-nil if the
;; first argument is "less than" the second.
;;
+;; You create a heap using `heap-create', add elements to it using
+;; `heap-add', delete and return the root of the heap using
+;; `heap-delete-root', and modify an element of the heap using
+;; `heap-modify'. A number of other convenience functions are
+;; also provided.
+;;
;; Note that this package implements a ternary heap, since ternary
;; heaps are about 12% more efficient than binary heaps for heaps
;; containing more than about 10 elements. And for very small heaps,
@@ -55,6 +61,14 @@
;;; Change log:
;;
+;; Version 0.2
+;; * fixed efficiency issue: vectors are no longer copied all the time
+;; (thanks to Stefan Monnier for pointing out this issue)
+;;
+;; Version 0.1.5
+;; * renamed `vswap' to `heap--vswap'
+;; * removed cl dependency
+;;
;; Version 0.1.4
;; * fixed internal function and macro names
;;
@@ -76,9 +90,6 @@
(provide 'heap)
-;; the only common lisp function required in `subseq', so this dependency
-;; should probably be removed
-(require 'cl)
@@ -87,47 +98,77 @@
;;; Internal functions for use in the heap package
-(defmacro heap--vect (heap)
- ;; Return the heap vector. ;; INTERNAL USE ONLY
- `(car (cdr ,heap))
+(defmacro heap--vect (heap) ; INTERNAL USE ONLY
+ ;; Return the heap vector.
+ `(aref ,heap 1)
+)
+
+
+(defmacro heap--set-vect (heap vect) ; INTERNAL USE ONLY
+ ;; Set the vector containing the heap itself to VECT.
+ `(aset ,heap 1 ,vect)
)
+(defmacro heap--cmpfun (heap) ; INTERNAL USE ONLY
+ ;; Return the comparison function of a heap.
+ `(aref ,heap 2)
+)
+
-(defmacro heap--cmpfun (heap)
- ;; Return the comparison function of a heap. ;; INTERNAL USE ONLY
- `(cdr (cdr ,heap))
+(defmacro heap--count (heap) ; INTERNAL USE ONLY
+ ;; Return number of items in HEAP
+ `(aref ,heap 3)
)
+(defmacro heap--set-count (heap count) ; INTERNAL USE ONLY
+ ;; Set number of items in HEAP
+ `(aset ,heap 3 ,count)
+)
-(defmacro heap--set-vect (heap vect)
- ;; Set the vector containing the heap itself to VECT.
- `(setcar (cdr ,heap) ,vect)
+
+(defmacro heap--size (heap) ; INTERNAL USE ONLY
+ ;; Return size of HEAP
+ `(aref ,heap 4)
+)
+
+
+(defmacro heap--set-size (heap size) ; INTERNAL USE ONLY
+ ;; Set size of HEAP
+ `(aset ,heap 4 ,size)
+)
+
+
+(defmacro heap--resize (heap) ; INTERNAL USE ONLY
+ ;; Return resize-factor of HEAP
+ `(aref ,heap 5)
)
-(defmacro heap--child (heap i)
- ;; Compare the 3 children of element I, and return element reference of the
- ;; smallest/largest (depending on whethen it's a min- or max-heap).
- ;; INTERNAL USE ONLY
- `(let* ((vect (heap--vect ,heap))
- (cmpfun (heap--cmpfun ,heap))
- (len (length vect)) (j nil) (k (* 3 ,i)))
- ;; Lots of if's in case I has less than three children.
- (if (>= (1+ k) len) nil
- (if (>= (+ 2 k) len) (1+ k)
- (setq j (if (funcall cmpfun (aref vect (1+ k)) (aref vect (+ 2 k)))
- (1+ k) (+ 2 k)))
- (if (>= (+ 3 k) len) j
- (if (funcall cmpfun (aref vect j) (aref vect (+ 3 k))) j (+ 3 k)))
- )))
+(defun heap--child (heap i) ; INTERNAL USE ONLY
+ ;; Compare the 3 children of element I, and return element reference of
+ ;; the smallest/largest (depending on whethen it's a min- or max-heap).
+ (let* ((vect (heap--vect heap))
+ (cmpfun (heap--cmpfun heap))
+ (count (heap--count heap))
+ (j nil) (k (* 3 i)))
+ ;; Lots of if's in case I has less than three children.
+ (if (>= (1+ k) count) nil
+ (if (>= (+ 2 k) count) (1+ k)
+ (setq j (if (funcall cmpfun (aref vect (1+ k))
+ (aref vect (+ 2 k)))
+ (1+ k) (+ 2 k)))
+ (if (>= (+ 3 k) count) j
+ (if (funcall cmpfun (aref vect j) (aref vect (+ 3 k)))
+ j (+ 3 k)))
+ )))
)
-(defmacro vswap (vect i j)
+(defmacro heap--vswap (vect i j) ; INTERNAL USE ONLY
;; Swap elements I and J of vector VECT.
`(let ((tmp (aref ,vect ,i)))
(aset ,vect ,i (aref ,vect ,j))
@@ -136,32 +177,31 @@
-(defun heap--sift-up (heap n)
- ;; Sift-up starting from element N of the heap vector belonging to
- ;; heap HEAP. ;; INTERNAL USE ONLY
+(defun heap--sift-up (heap n) ; INTERNAL USE ONLY
+ ;; Sift-up starting from element N of vector belonging to HEAP.
(let* ((i n) (j nil) (vect (heap--vect heap)) (v (aref vect n)))
;; Keep moving element up until it reaches top or is smaller/bigger
;; than its parent.
(while (and (> i 0)
(funcall (heap--cmpfun heap) v
(aref vect (setq j (/ (1- i) 3)))))
- (vswap vect i j)
+ (heap--vswap vect i j)
(setq i j)))
)
-(defun heap--sift-down (heap n)
- ;; Sift-down from element N of the heap vector belonging to
- ;; heap HEAP. ;; INTERNAL USE ONLY
+(defun heap--sift-down (heap n) ; INTERNAL USE ONLY
+ ;; Sift-down from element N of the heap vector belonging HEAP.
(let* ((vect (heap--vect heap))
(cmpfun (heap--cmpfun heap))
- (i n) (j (heap--child heap i)) (len (length vect)) (v (aref vect n)))
-
- ;; Keep moving the element down until it reaches the bottom of the tree or
- ;; reaches a position where it is bigger/smaller than all its children.
+ (i n) (j (heap--child heap i))
+ (v (aref vect n)))
+ ;; Keep moving the element down until it reaches the bottom of the
+ ;; tree or reaches a position where it is bigger/smaller than all its
+ ;; children.
(while (and j (funcall cmpfun (aref vect j) v))
- (vswap vect i j)
+ (heap--vswap vect i j)
(setq i j)
(setq j (heap--child heap i)))
)
@@ -175,40 +215,50 @@
;;; The public functions which operate on heaps.
-(defun heap-create (compare-function)
- "Create an empty heap using COMPARE-FUNCTION as the comparison
-function. COMPARE-FUNCTION takes two arguments, A and B, and returns non-nil
-or nil. To implement a max-heap, it should return non-nil if A is greater than
-B. To implemenet a min-heap, it should return non-nil if A is less than B."
- (cons 'HEAP (cons [] compare-function))
+(defun heap-create (compare-function &optional initial-size resize-factor)
+ "Create an empty heap with comparison function COMPARE-FUNCTION.
+
+COMPARE-FUNCTION takes two arguments, A and B, and returns
+non-nil or nil. To implement a max-heap, it should return non-nil
+if A is greater than B. To implemenet a min-heap, it should
+return non-nil if A is less than B.
+
+Optional argument INITIAL-SIZE sets the initial size of the heap,
+defaulting to 10. Optional argument RESIZE-FACTOR sets the factor
+by which the heap's size is increased if it runs out of space, defaulting
+to 1.5"
+ (unless initial-size (setq initial-size 10))
+ (unless resize-factor (setq resize-factor 1.5))
+ (vector 'HEAP (make-vector initial-size nil) compare-function
+ 0 initial-size resize-factor)
)
(defun heap-copy (heap)
"Return a copy of heap HEAP."
- (let ((newheap (heap-create (heap--cmpfun heap))))
- (heap--set-vect newheap (heap--vect heap))
+ (let ((newheap (heap-create (heap--size heap) (heap--cmpfun heap))))
+ (heap--set-vect newheap (vconcat (heap--vect heap) []))
newheap)
)
(defun heap-p (obj)
"Return t if OBJ is a heap, nil otherwise."
- (eq (car-safe obj) 'HEAP)
+ (and (vectorp obj) (eq (aref obj 0) 'HEAP))
)
(defun heap-empty (heap)
"Return t if the heap is empty, nil otherwise."
- (= 0 (length (heap--vect heap)))
+ (= 0 (heap--count heap))
)
(defun heap-size (heap)
"Return the number of entries in the heap."
- (length (heap--vect heap))
+ (heap--count heap)
)
@@ -221,27 +271,42 @@ B. To implemenet a min-heap, it should return non-nil if
A is less than B."
(defun heap-add (heap data)
- "Add DATA to the heap."
+ "Add DATA to the heap, and return DATA."
;; Add data to bottom of heap and sift-up from bottom.
- (heap--set-vect heap (vconcat (heap--vect heap) (vector data)))
- (heap--sift-up heap (1- (length (heap--vect heap))))
+ (let ((count (heap--count heap))
+ (size (heap--size heap))
+ (vect (heap--vect heap)))
+ ;; if there's no space left, grow the heap
+ (if (< count size)
+ (aset vect count data)
+ (heap--set-vect
+ heap (vconcat (heap--vect heap) (vector data)
+ (make-vector
+ (1- (ceiling (* size (1- (heap--resize heap)))))
+ nil)))
+ (heap--set-size heap (* 2 size)))
+ (setq count (heap--set-count heap (1+ (heap--count heap))))
+ (heap--sift-up heap (1- count)))
+ ;; return inserted data
+ data
)
(defun heap-delete-root (heap)
"Return the root of the heap and delete it from the heap."
- (let ((vect (heap--vect heap))
- (root nil) (len nil))
+ (let (vect root (count (heap--count heap)))
- ;; Deal with special cases of empty heap and heap with just one element.
- (if (heap-empty heap) nil
- (setq len (length vect))
+ ;; deal with empty heaps and heaps with just one element
+ (if (= count 0) nil
+ (setq vect (heap--vect heap))
(setq root (aref vect 0))
- (if (= 1 len) (heap--set-vect heap [])
+ (heap--set-count heap (1- (heap--count heap)))
+ (if (= 1 count) (heap--set-vect heap (make-vector 10 nil))
;; Delete root, swap last element to top, and sift-down from top.
- (heap--set-vect heap (vconcat (vector (aref vect (1- len)))
- (subseq vect 1 (1- len))))
+ (setq vect (heap--vect heap))
+ (aset vect 0 (aref vect (1- count)))
+ (aset vect (1- count) nil)
(heap--sift-down heap 0))
root)
)
@@ -250,21 +315,25 @@ B. To implemenet a min-heap, it should return non-nil if
A is less than B."
(defun heap-modify (heap match-function data)
- "Replace the first heap entry identified by MATCH-FUNCTION with DATA, if a
-match exists. Return t if there was a match, nil otherwise.
+ "Replace the first heap entry identified by MATCH-FUNCTION
+with DATA, if a match exists. Return t if there was a match, nil
+otherwise.
-The function MATCH-FUNCTION should take one argument of the type stored in the
-heap, and return non-nil if it should be modified, nil otherwise.
+The function MATCH-FUNCTION should take one argument of the type
+stored in the heap, and return non-nil if it should be modified,
+nil otherwise.
Note that only the match highest up the heap is modified."
- (let ((vect (heap--vect heap)) (i 0))
+ (let ((vect (heap--vect heap))
+ (count (heap--count heap))
+ (i 0))
;; search vector for the first match
- (while (and (< i (length vect))
+ (while (and (< i count)
(not (funcall match-function (aref vect i))))
(setq i (1+ i)))
;; if a match was found, modify it
- (if (< i (length vect))
+ (if (< i count)
(let ((olddata (aref vect i)))
(aset vect i data)
;; if the new data is greater than old data, sift-up, otherwise
- [elpa] branch externals/heap created (now 32e75bb), Stefan Monnier, 2020/12/14
- [elpa] externals/heap 37bc0e9 05/31: Version 0.10 of the predictive completion package., Stefan Monnier, 2020/12/14
- [elpa] externals/heap 03a876d 02/31: Version 0.2 of the predictive completion package., Stefan Monnier, 2020/12/14
- [elpa] externals/heap ceb5dd1 21/31: Trivial whitespace tidying., Stefan Monnier, 2020/12/14
- [elpa] externals/heap 17429ee 07/31: Version 0.12 of the predictive completion package.,
Stefan Monnier <=
- [elpa] externals/heap 55d47fd 11/31: Fixed ancient but overlooked bug in heap resizing in heap-add., Stefan Monnier, 2020/12/14
- [elpa] externals/heap 9bcd8d3 16/31: Added heap-build function for efficiently building a heap out of a vector., Stefan Monnier, 2020/12/14
- [elpa] externals/heap ed90e4d 09/31: Adding missing 'buffer setting to customization menu for predictive-auto-add-to-dict., Stefan Monnier, 2020/12/14
- [elpa] externals/heap f74c766 15/31: Converted heap data structures to defstructs., Stefan Monnier, 2020/12/14
- [elpa] externals/heap e354b4f 19/31: Revert default heap size to 10., Stefan Monnier, 2020/12/14
- [elpa] externals/heap e2c16be 06/31: Version 0.10.3 of the predictive completion package., Stefan Monnier, 2020/12/14
- [elpa] externals/heap 75b42f4 04/31: Version 0.9.1 of the predictive completion package., Stefan Monnier, 2020/12/14
- [elpa] externals/heap 2d51c84 01/31: Version 0.1 of the predictive completion package., Stefan Monnier, 2020/12/14
- [elpa] externals/heap 227de61 03/31: Version 0.7 of the predictive completion package., Stefan Monnier, 2020/12/14
- [elpa] externals/heap da9637e 25/31: Added heap-clear function., Stefan Monnier, 2020/12/14