[Git][cmucl/cmucl][issue-240-set-diff-with-hash-table] 2 commits: Prefer list2 when both lists have the same length
Raymond Toy (@rtoy)
gitlab at common-lisp.net
Mon Jun 19 20:49:50 UTC 2023
Raymond Toy pushed to branch issue-240-set-diff-with-hash-table at cmucl / cmucl
Commits:
ac30347e by Raymond Toy at 2023-06-19T13:45:44-07:00
Prefer list2 when both lists have the same length
Also add some comments.
- - - - -
57f0451c by Raymond Toy at 2023-06-19T13:48:29-07:00
Allow quick exit in set-difference
Also, now that set-difference is pretty large, don't declare it as
maybe-inline.
- - - - -
1 changed file:
- src/code/list.lisp
Changes:
=====================================
src/code/list.lisp
=====================================
@@ -45,7 +45,7 @@
tree-equal list-length nth %setnth nthcdr last make-list append
copy-list copy-alist copy-tree revappend nconc nreconc butlast
nbutlast ldiff member member-if member-if-not tailp adjoin union
- nunion intersection nintersection set-difference nset-difference
+ nunion intersection nintersection nset-difference
set-exclusive-or nset-exclusive-or subsetp acons pairlis assoc
assoc-if assoc-if-not rassoc rassoc-if rassoc-if-not subst subst-if
subst-if-not nsubst nsubst-if nsubst-if-not sublis nsublis))
@@ -744,11 +744,13 @@
list
(cons item list)))
+;; The minimum length of a list before we can use a hashtable
(defparameter *min-list-length-for-hashtable*
15)
;; Convert a list to a hashtable. Given 2 lists, find the shorter of
-;; the two lists and add the shorter list to a hashtable.
+;; the two lists and add the shorter list to a hashtable. Returns the
+;; hashtable and the shorter list.
(defun list-to-hashtable (list1 list2 &key test test-not key)
;; Don't currently support test-not when converting a list to a hashtable
(unless test-not
@@ -763,13 +765,18 @@
(unless hash-test
(return-from list-to-hashtable (values nil nil)))
(multiple-value-bind (len shorter-list)
+ ;; Find the list with the shorter length. If they're they
+ ;; same, we prefer the second list to the first list since
+ ;; the hashtable implementation is slightly simplier.
(do ((length 0 (1+ length))
(l1 list1 (cdr l1))
(l2 list2 (cdr l2)))
- ((cond ((null l1)
- (return (values length list1)))
- ((null l2)
- (return (values length list2))))))
+ ((cond ((null l2)
+ (return (values length list2)))
+ ((null l1)
+ (return (values length list1))))))
+ ;; If the list is too short, the hashtable makes things
+ ;; slower. We also need to balance memory usage.
(when (< len *min-list-length-for-hashtable*)
(return-from list-to-hashtable (values nil nil)))
(cond ((eq shorter-list list2)
@@ -855,18 +862,20 @@
(declare (inline member))
(if (and testp notp)
(error "Test and test-not both supplied."))
+ ;; Quick exit
+ (when (null list)
+ (return-from set-difference list1))
+
(multiple-value-bind (hashtable shorter-list)
(list-to-hashtable list1 list2 :key key :test test :test-not test-not)
(cond ((null hashtable)
;; Default implementation because we didn't create the hash
;; table.
- (if (null list2)
- list1
- (let ((res nil))
- (dolist (elt list1)
- (if (not (with-set-keys (member (apply-key key elt) list2)))
- (push elt res)))
- res)))
+ (let ((res nil))
+ (dolist (elt list1)
+ (if (not (with-set-keys (member (apply-key key elt) list2)))
+ (push elt res)))
+ res))
((eq shorter-list list2)
;; list2 was placed in hash table.
(let (diff)
View it on GitLab: https://gitlab.common-lisp.net/cmucl/cmucl/-/compare/653dc42ff6285a475709fe25fa9f5d54c998f4ab...57f0451ca3e5a2af12b06b37138b2465dc65960c
--
View it on GitLab: https://gitlab.common-lisp.net/cmucl/cmucl/-/compare/653dc42ff6285a475709fe25fa9f5d54c998f4ab...57f0451ca3e5a2af12b06b37138b2465dc65960c
You're receiving this email because of your account on gitlab.common-lisp.net.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/cmucl-cvs/attachments/20230619/4e0469c9/attachment-0001.html>
More information about the cmucl-cvs
mailing list