Raymond Toy pushed to branch issue-249-replace-lea-in-arith at cmucl / cmucl
Commits:
-
33f11724
by Raymond Toy at 2023-08-12T07:34:55-07:00
-
a8ced15b
by Carl Shapiro at 2023-08-14T04:45:23+00:00
-
310e41eb
by Carl Shapiro at 2023-08-14T04:45:41+00:00
-
19a305de
by Raymond Toy at 2023-08-16T14:28:11+00:00
-
9d593e3a
by Raymond Toy at 2023-08-16T14:28:55+00:00
-
55c01f44
by Raymond Toy at 2023-08-17T13:33:59+00:00
-
14d847f0
by Raymond Toy at 2023-08-17T13:34:15+00:00
-
c9ce7574
by Raymond Toy at 2023-08-17T13:36:18+00:00
-
5c7536f0
by Raymond Toy at 2023-08-17T13:36:44+00:00
-
181508a9
by Raymond Toy at 2023-08-17T06:47:03-07:00
-
12809996
by Raymond Toy at 2023-08-18T08:39:02-07:00
5 changed files:
- benchmarks/cl-bench/files/math.lisp
- src/code/list.lisp
- src/compiler/seqtran.lisp
- + tests/list.lisp
- + tests/sets.lisp
Changes:
1 | 1 | ;;; math.lisp -- various numerical operations
|
2 | 2 | ;;
|
3 | -;; Time-stamp: <2004-01-05 emarsden>
|
|
3 | +;; Time-stamp: <2023-08-12 07:34:28 toy>
|
|
4 | 4 | ;;
|
5 | 5 | ;; some basic mathematical benchmarks
|
6 | 6 | |
... | ... | @@ -56,7 +56,7 @@ |
56 | 56 | ;; calculate the "level" of a point in the Mandebrot Set, which is the
|
57 | 57 | ;; number of iterations taken to escape to "infinity" (points that
|
58 | 58 | ;; don't escape are included in the Mandelbrot Set). This version is
|
59 | -;; intended to test performance when programming in nave math-style.
|
|
59 | +;; intended to test performance when programming in naive math-style.
|
|
60 | 60 | (defun mset-level/complex (c)
|
61 | 61 | (declare (type complex c))
|
62 | 62 | (loop :for z = #c(0 0) :then (+ (* z z) c)
|
... | ... | @@ -45,7 +45,7 @@ |
45 | 45 | tree-equal list-length nth %setnth nthcdr last make-list append
|
46 | 46 | copy-list copy-alist copy-tree revappend nconc nreconc butlast
|
47 | 47 | nbutlast ldiff member member-if member-if-not tailp adjoin union
|
48 | - nunion intersection nintersection set-difference nset-difference
|
|
48 | + nunion intersection nintersection nset-difference
|
|
49 | 49 | set-exclusive-or nset-exclusive-or subsetp acons pairlis assoc
|
50 | 50 | assoc-if assoc-if-not rassoc rassoc-if rassoc-if-not subst subst-if
|
51 | 51 | subst-if-not nsubst nsubst-if nsubst-if-not sublis nsublis))
|
... | ... | @@ -744,6 +744,39 @@ |
744 | 744 | list
|
745 | 745 | (cons item list)))
|
746 | 746 | |
747 | +;; The minimum length of a list before we can use a hashtable. This
|
|
748 | +;; was determined experimentally.
|
|
749 | +(defparameter *min-list-length-for-hashtable*
|
|
750 | + 15)
|
|
751 | + |
|
752 | +;; Convert a list to a hashtable. The hashtable does not handle
|
|
753 | +;; duplicated values in the list. Returns the hashtable.
|
|
754 | +(defun list-to-hashtable (list key test test-not)
|
|
755 | + ;; Don't currently support test-not when converting a list to a hashtable
|
|
756 | + (unless test-not
|
|
757 | + (let ((hash-test (let ((test-fn (if (and (symbolp test)
|
|
758 | + (fboundp test))
|
|
759 | + (fdefinition test)
|
|
760 | + test)))
|
|
761 | + (cond ((eql test-fn #'eq) 'eq)
|
|
762 | + ((eql test-fn #'eql) 'eql)
|
|
763 | + ((eql test-fn #'equal) 'equal)
|
|
764 | + ((eql test-fn #'equalp) 'equalp)))))
|
|
765 | + (unless hash-test
|
|
766 | + (return-from list-to-hashtable nil))
|
|
767 | + ;; If the list is too short, the hashtable makes things
|
|
768 | + ;; slower. We also need to balance memory usage.
|
|
769 | + (let ((len 0))
|
|
770 | + ;; Compute list length ourselves.
|
|
771 | + (dolist (item list)
|
|
772 | + (declare (ignore item))
|
|
773 | + (incf len))
|
|
774 | + (when (< len *min-list-length-for-hashtable*)
|
|
775 | + (return-from list-to-hashtable nil))
|
|
776 | + (let ((hashtable (make-hash-table :test hash-test :size len)))
|
|
777 | + (dolist (item list)
|
|
778 | + (setf (gethash (apply-key key item) hashtable) item))
|
|
779 | + hashtable)))))
|
|
747 | 780 | |
748 | 781 | ;;; UNION -- Public.
|
749 | 782 | ;;;
|
... | ... | @@ -755,11 +788,18 @@ |
755 | 788 | (defun union (list1 list2 &key key (test #'eql testp) (test-not nil notp))
|
756 | 789 | "Returns the union of list1 and list2."
|
757 | 790 | (declare (inline member))
|
758 | - (when (and testp notp) (error (intl:gettext "Test and test-not both supplied.")))
|
|
759 | - (let ((res list2))
|
|
760 | - (dolist (elt list1)
|
|
761 | - (unless (with-set-keys (member (apply-key key elt) list2))
|
|
762 | - (push elt res)))
|
|
791 | + (when (and testp notp)
|
|
792 | + (error (intl:gettext "Test and test-not both supplied.")))
|
|
793 | + (let ((res list2)
|
|
794 | + (hashtable (list-to-hashtable list2 key test test-not)))
|
|
795 | + (cond (hashtable
|
|
796 | + (dolist (item list1)
|
|
797 | + (unless (nth-value 1 (gethash (apply-key key item) hashtable))
|
|
798 | + (push item res))))
|
|
799 | + ((null hashtable)
|
|
800 | + (dolist (item list1)
|
|
801 | + (unless (with-set-keys (member (apply-key key item) list2))
|
|
802 | + (push item res)))))
|
|
763 | 803 | res))
|
764 | 804 | |
765 | 805 | ;;; Destination and source are setf-able and many-evaluable. Sets the source
|
... | ... | @@ -792,11 +832,20 @@ |
792 | 832 | (declare (inline member))
|
793 | 833 | (if (and testp notp)
|
794 | 834 | (error "Test and test-not both supplied."))
|
795 | - (let ((res nil))
|
|
796 | - (dolist (elt list1)
|
|
797 | - (if (with-set-keys (member (apply-key key elt) list2))
|
|
798 | - (push elt res)))
|
|
799 | - res))
|
|
835 | + (let ((hashtable
|
|
836 | + (list-to-hashtable list2 key test test-not)))
|
|
837 | + (cond (hashtable
|
|
838 | + (let ((res nil))
|
|
839 | + (dolist (item list1)
|
|
840 | + (when (nth-value 1 (gethash (apply-key key item) hashtable))
|
|
841 | + (push item res)))
|
|
842 | + res))
|
|
843 | + ((null hashtable)
|
|
844 | + (let ((res nil))
|
|
845 | + (dolist (elt list1)
|
|
846 | + (if (with-set-keys (member (apply-key key elt) list2))
|
|
847 | + (push elt res)))
|
|
848 | + res)))))
|
|
800 | 849 | |
801 | 850 | (defun nintersection (list1 list2 &key key
|
802 | 851 | (test #'eql testp) (test-not nil notp))
|
... | ... | @@ -812,20 +861,32 @@ |
812 | 861 | (setq list1 (Cdr list1))))
|
813 | 862 | res))
|
814 | 863 | |
815 | -(defun set-difference (list1 list2 &key key
|
|
816 | - (test #'eql testp) (test-not nil notp))
|
|
864 | +(defun set-difference (list1 list2 &key key (test #'eql testp) (test-not nil notp))
|
|
817 | 865 | "Returns the elements of list1 which are not in list2."
|
818 | 866 | (declare (inline member))
|
819 | 867 | (if (and testp notp)
|
820 | 868 | (error "Test and test-not both supplied."))
|
821 | - (if (null list2)
|
|
822 | - list1
|
|
823 | - (let ((res nil))
|
|
824 | - (dolist (elt list1)
|
|
825 | - (if (not (with-set-keys (member (apply-key key elt) list2)))
|
|
826 | - (push elt res)))
|
|
827 | - res)))
|
|
828 | - |
|
869 | + ;; Quick exit
|
|
870 | + (when (null list2)
|
|
871 | + (return-from set-difference list1))
|
|
872 | + |
|
873 | + (let ((hashtable
|
|
874 | + (list-to-hashtable list2 key test test-not)))
|
|
875 | + (cond (hashtable
|
|
876 | + ;; list2 was placed in hash table.
|
|
877 | + (let ((res nil))
|
|
878 | + (dolist (item list1)
|
|
879 | + (unless (nth-value 1 (gethash (apply-key key item) hashtable))
|
|
880 | + (push item res)))
|
|
881 | + res))
|
|
882 | + ((null hashtable)
|
|
883 | + ;; Default implementation because we didn't create the hash
|
|
884 | + ;; table.
|
|
885 | + (let ((res nil))
|
|
886 | + (dolist (item list1)
|
|
887 | + (if (not (with-set-keys (member (apply-key key item) list2)))
|
|
888 | + (push item res)))
|
|
889 | + res)))))
|
|
829 | 890 | |
830 | 891 | (defun nset-difference (list1 list2 &key key
|
831 | 892 | (test #'eql testp) (test-not nil notp))
|
... | ... | @@ -1050,7 +1111,10 @@ |
1050 | 1111 | (setf (car l) (cdar l)))
|
1051 | 1112 | (setq res (apply function (nreverse args)))
|
1052 | 1113 | (case accumulate
|
1053 | - (:nconc (setq temp (last (nconc temp res))))
|
|
1114 | + (:nconc (when res
|
|
1115 | + (let ((next-temp (last res)))
|
|
1116 | + (rplacd temp res)
|
|
1117 | + (setq temp next-temp))))
|
|
1054 | 1118 | (:list (rplacd temp (list res))
|
1055 | 1119 | (setq temp (cdr temp)))))))
|
1056 | 1120 |
... | ... | @@ -36,12 +36,18 @@ |
36 | 36 | (ecase accumulate
|
37 | 37 | (:nconc
|
38 | 38 | (let ((temp (gensym))
|
39 | - (map-result (gensym)))
|
|
39 | + (map-result (gensym))
|
|
40 | + (res (gensym))
|
|
41 | + (next-temp (gensym)))
|
|
40 | 42 | `(let ((,map-result (list nil)))
|
41 | 43 | (declare (dynamic-extent ,map-result))
|
42 | 44 | (do-anonymous ((,temp ,map-result) . ,(do-clauses))
|
43 | 45 | (,endtest (cdr ,map-result))
|
44 | - (setq ,temp (last (nconc ,temp ,call)))))))
|
|
46 | + (let ((,res ,call))
|
|
47 | + (when ,res
|
|
48 | + (let ((,next-temp (last ,res)))
|
|
49 | + (rplacd ,temp ,res)
|
|
50 | + (setq ,temp ,next-temp))))))))
|
|
45 | 51 | (:list
|
46 | 52 | (let ((temp (gensym))
|
47 | 53 | (map-result (gensym)))
|
1 | +(defpackage "LIST-TESTS"
|
|
2 | + (:use "COMMON-LISP"
|
|
3 | + "LISP-UNIT"))
|
|
4 | + |
|
5 | +(in-package "LIST-TESTS")
|
|
6 | + |
|
7 | +(define-test mapcan-empty-list-returns-nil
|
|
8 | + (locally (declare (notinline mapcan))
|
|
9 | + (assert-equal '() (mapcan #'identity '())))
|
|
10 | + (locally (declare (inline mapcan))
|
|
11 | + (assert-equal '() (mapcan #'identity '()))))
|
|
12 | + |
|
13 | +(define-test mapcon-empty-list-returns-nil
|
|
14 | + (locally (declare (notinline mapcon))
|
|
15 | + (assert-equal '() (mapcon #'identity '())))
|
|
16 | + (locally (declare (inline mapcon))
|
|
17 | + (assert-equal '() (mapcon #'identity '()))))
|
|
18 | + |
|
19 | +(define-test mapcan-accumulate-non-nil-signals-type-error
|
|
20 | + (locally (declare (notinline mapcan))
|
|
21 | + (assert-error 'type-error (mapcan #'identity (list 42))))
|
|
22 | + (locally (declare (inline mapcan))
|
|
23 | + (assert-error 'type-error (mapcan #'identity (list 42)))))
|
|
24 | + |
|
25 | +(define-test mapcon-accumulate-non-nil-signals-type-error
|
|
26 | + (locally (declare (notinline mapcan))
|
|
27 | + (assert-error 'type-error (mapcon #'car (list 42))))
|
|
28 | + (locally (declare (inline mapcan))
|
|
29 | + (assert-error 'type-error (mapcon #'car (list 42)))))
|
|
30 | + |
|
31 | +(define-test mapcan-accumulate-nil-returns-nil
|
|
32 | + (locally (declare (notinline mapcan))
|
|
33 | + (assert-equal '() (mapcan (constantly nil) '(1)))
|
|
34 | + (assert-equal '() (mapcan (constantly nil) '(1 2)))
|
|
35 | + (assert-equal '() (mapcan (constantly nil) '(1 2 3))))
|
|
36 | + (locally (declare (inline mapcan))
|
|
37 | + (assert-equal '() (mapcan (constantly nil) '(1)))
|
|
38 | + (assert-equal '() (mapcan (constantly nil) '(1 2)))
|
|
39 | + (assert-equal '() (mapcan (constantly nil) '(1 2 3)))))
|
|
40 | + |
|
41 | +(define-test mapcon-accumulate-nil-returns-nil
|
|
42 | + (locally (declare (notinline mapcon))
|
|
43 | + (assert-equal '() (mapcon (constantly nil) '(1)))
|
|
44 | + (assert-equal '() (mapcon (constantly nil) '(1 2)))
|
|
45 | + (assert-equal '() (mapcon (constantly nil) '(1 2 3))))
|
|
46 | + (locally (declare (inline mapcon))
|
|
47 | + (assert-equal '() (mapcon (constantly nil) '(1)))
|
|
48 | + (assert-equal '() (mapcon (constantly nil) '(1 2)))
|
|
49 | + (assert-equal '() (mapcon (constantly nil) '(1 2 3)))))
|
|
50 | + |
|
51 | +(define-test mapcan-accumulate-one-list-returns-same-list
|
|
52 | + (locally (declare (notinline mapcan))
|
|
53 | + (let ((list1 (list 1)))
|
|
54 | + (assert-eq list1 (mapcan (constantly list1) '(nil)))))
|
|
55 | + (locally (declare (inline mapcan))
|
|
56 | + (let ((list1 (list 1)))
|
|
57 | + (assert-eq list1 (mapcan (constantly list1) '(nil))))))
|
|
58 | + |
|
59 | +(define-test mapcon-accumulate-one-list-returns-same-list
|
|
60 | + (locally (declare (notinline mapcon))
|
|
61 | + (let ((list1 (list 1)))
|
|
62 | + (assert-eq list1 (mapcon (constantly list1) '(nil)))))
|
|
63 | + (locally (declare (inline mapcon))
|
|
64 | + (let ((list1 (list 1)))
|
|
65 | + (assert-eq list1 (mapcon (constantly list1) '(nil))))))
|
|
66 | + |
|
67 | +(define-test mapcan-accumulate-two-lists-returns-same-lists
|
|
68 | + (locally (declare (notinline mapcan))
|
|
69 | + (let* ((list1 (list 1))
|
|
70 | + (list2 (list 2))
|
|
71 | + (list12 (mapcan #'identity (list list1 list2))))
|
|
72 | + (assert-eq list1 list12)
|
|
73 | + (assert-eq list2 (cdr list12))))
|
|
74 | + (locally (declare (inline mapcan))
|
|
75 | + (let* ((list1 (list 1))
|
|
76 | + (list2 (list 2))
|
|
77 | + (list12 (mapcan #'identity (list list1 list2))))
|
|
78 | + (assert-eq list1 list12)
|
|
79 | + (assert-eq list2 (cdr list12)))))
|
|
80 | + |
|
81 | +(define-test mapcon-accumulate-two-lists-returns-same-lists
|
|
82 | + (locally (declare (notinline mapcon))
|
|
83 | + (let* ((list1 (list 1))
|
|
84 | + (list2 (list 2))
|
|
85 | + (list12 (mapcon #'car (list list1 list2))))
|
|
86 | + (assert-eq list1 list12)
|
|
87 | + (assert-eq list2 (cdr list12))))
|
|
88 | + (locally (declare (inline mapcon))
|
|
89 | + (let* ((list1 (list 1))
|
|
90 | + (list2 (list 2))
|
|
91 | + (list12 (mapcon #'car (list list1 list2))))
|
|
92 | + (assert-eq list1 list12)
|
|
93 | + (assert-eq list2 (cdr list12)))))
|
|
94 | + |
|
95 | +(define-test mapcan-accumulate-two-lists-skips-nil-returns-same-lists
|
|
96 | + (locally (declare (notinline mapcan))
|
|
97 | + (let* ((list1 (list 1))
|
|
98 | + (list2 (list 2))
|
|
99 | + (list12 (mapcan #'identity (list nil list1 list2))))
|
|
100 | + (assert-eq list1 list12)
|
|
101 | + (assert-eq list2 (cdr list12)))
|
|
102 | + (let* ((list1 (list 1))
|
|
103 | + (list2 (list 2))
|
|
104 | + (list12 (mapcan #'identity (list list1 nil list2))))
|
|
105 | + (assert-eq list1 list12)
|
|
106 | + (assert-eq list2 (cdr list12)))
|
|
107 | + (let* ((list1 (list 1))
|
|
108 | + (list2 (list 2))
|
|
109 | + (list12 (mapcan #'identity (list list1 list2 nil))))
|
|
110 | + (assert-eq list1 list12)
|
|
111 | + (assert-eq list2 (cdr list12))))
|
|
112 | + (locally (declare (inline mapcan))
|
|
113 | + (let* ((list1 (list 1))
|
|
114 | + (list2 (list 2))
|
|
115 | + (list12 (mapcan #'identity (list nil list1 list2))))
|
|
116 | + (assert-eq list1 list12)
|
|
117 | + (assert-eq list2 (cdr list12)))
|
|
118 | + (let* ((list1 (list 1))
|
|
119 | + (list2 (list 2))
|
|
120 | + (list12 (mapcan #'identity (list list1 nil list2))))
|
|
121 | + (assert-eq list1 list12)
|
|
122 | + (assert-eq list2 (cdr list12)))
|
|
123 | + (let* ((list1 (list 1))
|
|
124 | + (list2 (list 2))
|
|
125 | + (list12 (mapcan #'identity (list list1 list2 nil))))
|
|
126 | + (assert-eq list1 list12)
|
|
127 | + (assert-eq list2 (cdr list12)))))
|
|
128 | + |
|
129 | +(define-test mapcon-accumulate-two-lists-skips-nil-returns-same-lists
|
|
130 | + (locally (declare (notinline mapcon))
|
|
131 | + (let* ((list1 (list 1))
|
|
132 | + (list2 (list 2))
|
|
133 | + (list12 (mapcon #'car (list nil list1 list2))))
|
|
134 | + (assert-eq list1 list12)
|
|
135 | + (assert-eq list2 (cdr list12)))
|
|
136 | + (let* ((list1 (list 1))
|
|
137 | + (list2 (list 2))
|
|
138 | + (list12 (mapcon #'car (list list1 nil list2))))
|
|
139 | + (assert-eq list1 list12)
|
|
140 | + (assert-eq list2 (cdr list12)))
|
|
141 | + (let* ((list1 (list 1))
|
|
142 | + (list2 (list 2))
|
|
143 | + (list12 (mapcon #'car (list list1 list2 nil))))
|
|
144 | + (assert-eq list1 list12)
|
|
145 | + (assert-eq list2 (cdr list12))))
|
|
146 | + (locally (declare (inline mapcon))
|
|
147 | + (let* ((list1 (list 1))
|
|
148 | + (list2 (list 2))
|
|
149 | + (list12 (mapcon #'car (list nil list1 list2))))
|
|
150 | + (assert-eq list1 list12)
|
|
151 | + (assert-eq list2 (cdr list12)))
|
|
152 | + (let* ((list1 (list 1))
|
|
153 | + (list2 (list 2))
|
|
154 | + (list12 (mapcon #'car (list list1 nil list2))))
|
|
155 | + (assert-eq list1 list12)
|
|
156 | + (assert-eq list2 (cdr list12)))
|
|
157 | + (let* ((list1 (list 1))
|
|
158 | + (list2 (list 2))
|
|
159 | + (list12 (mapcon #'car (list list1 list2 nil))))
|
|
160 | + (assert-eq list1 list12)
|
|
161 | + (assert-eq list2 (cdr list12)))))
|
|
162 | + |
|
163 | +(define-test mapcan-accumulate-same-list-twice-returns-circular-list
|
|
164 | + (locally (declare (notinline mapcan))
|
|
165 | + (let ((list12 (list 1 2)))
|
|
166 | + ;; check that list12 equals #1=(1 2 . #1#)
|
|
167 | + (assert-eq list12 (mapcan (constantly list12) '(nil nil)))
|
|
168 | + (assert-eql 1 (elt list12 0))
|
|
169 | + (assert-eql 2 (elt list12 1))
|
|
170 | + (assert-eq (nthcdr 2 list12) list12)))
|
|
171 | + (locally (declare (inline mapcan))
|
|
172 | + (let ((list12 (list 1 2)))
|
|
173 | + ;; check that list12 equals #1=(1 2 . #1#)
|
|
174 | + (assert-eq list12 (mapcan (constantly list12) '(nil nil)))
|
|
175 | + (assert-eql 1 (elt list12 0))
|
|
176 | + (assert-eql 2 (elt list12 1))
|
|
177 | + (assert-eq (nthcdr 2 list12) list12))))
|
|
178 | + |
|
179 | +(define-test mapcon-accumulate-same-list-twice-returns-circular-list
|
|
180 | + (locally (declare (notinline mapcon))
|
|
181 | + (let ((list12 (list 1 2)))
|
|
182 | + ;; check that list12 equals #1=(1 2 . #1#)
|
|
183 | + (assert-eq list12 (mapcon (constantly list12) '(nil nil)))
|
|
184 | + (assert-eql 1 (elt list12 0))
|
|
185 | + (assert-eql 2 (elt list12 1))
|
|
186 | + (assert-eq (nthcdr 2 list12) list12)))
|
|
187 | + (locally (declare (notinline mapcon))
|
|
188 | + (let ((list12 (list 1 2)))
|
|
189 | + ;; check that list12 equals #1=(1 2 . #1#)
|
|
190 | + (assert-eq list12 (mapcon (constantly list12) '(nil nil)))
|
|
191 | + (assert-eql 1 (elt list12 0))
|
|
192 | + (assert-eql 2 (elt list12 1))
|
|
193 | + (assert-eq (nthcdr 2 list12) list12)))) |
1 | +;; Tests for sets
|
|
2 | + |
|
3 | +(defpackage :sets-tests
|
|
4 | + (:use :cl :lisp-unit))
|
|
5 | + |
|
6 | +(in-package "SETS-TESTS")
|
|
7 | + |
|
8 | +(define-test set-diff.hash-eql
|
|
9 | + (:tag :issues)
|
|
10 | + ;; For set-difference to use hashtables by making the threshold
|
|
11 | + ;; small.
|
|
12 | + (let ((lisp::*min-list-length-for-hashtable* 2))
|
|
13 | + (assert-equal '(2 2 1)
|
|
14 | + (set-difference '(1 2 2 3) '(3 4)))
|
|
15 | + (assert-equal '(2 2 1)
|
|
16 | + (set-difference '(1 2 2 3) '(3 4 5 6 7 8)))
|
|
17 | + (assert-equal '(2 2 1)
|
|
18 | + (set-difference '(1 2 2 3) '(3 4)
|
|
19 | + :test #'eql))
|
|
20 | + (assert-equal '(2 2 1)
|
|
21 | + (set-difference '(1 2 2 3) '(3 4 5 6 7 8)
|
|
22 | + :test #'eql))))
|
|
23 | + |
|
24 | +(define-test set-diff.hash-eq
|
|
25 | + (:tag :issues)
|
|
26 | + (let ((lisp::*min-list-length-for-hashtable* 2))
|
|
27 | + (assert-equal '(b b a)
|
|
28 | + (set-difference '(a b b c) '(c d e) :test 'eq))
|
|
29 | + (assert-equal '(b b a)
|
|
30 | + (set-difference '(a b b c) '(c d e f g h) :test 'eq))
|
|
31 | + (assert-equal '(b b a)
|
|
32 | + (set-difference '(a b b c) '(c d e) :test #'eq))
|
|
33 | + (assert-equal '(b b a)
|
|
34 | + (set-difference '(a b b c) '(c d e f g h) :test #'eq))))
|
|
35 | + |
|
36 | +(define-test set-diff.hash-equal
|
|
37 | + (:tag :issues)
|
|
38 | + (let ((lisp::*min-list-length-for-hashtable* 2))
|
|
39 | + (assert-equal '("b" "b" "a")
|
|
40 | + (set-difference '("a" "b" "b" "c")
|
|
41 | + '("c" "d" "e")
|
|
42 | + :test 'equal))
|
|
43 | + (assert-equal '("b" "b" "a")
|
|
44 | + (set-difference '("a" "b" "b" "c")
|
|
45 | + '("c" "d" "e" "f" "g" "h")
|
|
46 | + :test 'equal))
|
|
47 | + (assert-equal '("b" "b" "a")
|
|
48 | + (set-difference '("a" "b" "b" "c")
|
|
49 | + '("c" "d" "e")
|
|
50 | + :test #'equal))
|
|
51 | + (assert-equal '("b" "b" "a")
|
|
52 | + (set-difference '("a" "b" "b" "c")
|
|
53 | + '("c" "d" "e" "f" "g" "h")
|
|
54 | + :test #'equal))))
|
|
55 | + |
|
56 | +(define-test set-diff.hash-equalp
|
|
57 | + (:tag :issues)
|
|
58 | + (let ((lisp::*min-list-length-for-hashtable* 2))
|
|
59 | + (assert-equal '("b" "b" "a")
|
|
60 | + (set-difference '("a" "b" "b" "c")
|
|
61 | + '("C" "d" "e")
|
|
62 | + :test 'equalp))
|
|
63 | + (assert-equal '("b" "b" "a")
|
|
64 | + (set-difference '("a" "b" "b" "C")
|
|
65 | + '("c" "D" "e" "f" "g" "h")
|
|
66 | + :test 'equalp))
|
|
67 | + (assert-equal '("b" "b" "a")
|
|
68 | + (set-difference '("a" "b" "b" "c")
|
|
69 | + '("C" "d" "e")
|
|
70 | + :test #'equalp))
|
|
71 | + (assert-equal '("b" "b" "a")
|
|
72 | + (set-difference '("a" "b" "b" "C")
|
|
73 | + '("c" "D" "e" "f" "g" "h")
|
|
74 | + :test #'equalp))))
|
|
75 | + |
|
76 | +;; Simple test that we handle a key correctly
|
|
77 | +(define-test set-diff.hash-eql-with-key
|
|
78 | + (let ((lisp::*min-list-length-for-hashtable* 2))
|
|
79 | + (assert-equal '((3 "b") (2 "b"))
|
|
80 | + (set-difference '((1 "a") (2 "b") (3 "b"))
|
|
81 | + '((1 "a") (4 "c") (5 "d"))
|
|
82 | + :key #'first))))
|
|
83 | + |
|
84 | +(define-test set-diff.test-and-test-not
|
|
85 | + (assert-error 'simple-error
|
|
86 | + (set-difference '(1 2)
|
|
87 | + '(3 4)
|
|
88 | + :test 'eql
|
|
89 | + :test-not 'eql)))
|
|
90 | + |
|
91 | +
|
|
92 | + |
|
93 | +(define-test union.hash-eql
|
|
94 | + (:tag :issues)
|
|
95 | + ;; For union to use hashtables by making the threshold
|
|
96 | + ;; small.
|
|
97 | + (let ((lisp::*min-list-length-for-hashtable* 2))
|
|
98 | + (assert-equal '(2 2 1 3 4)
|
|
99 | + (union '(1 2 2 3) '(3 4)))
|
|
100 | + (assert-equal '(2 2 1 3 4 5 6 7 8)
|
|
101 | + (union '(1 2 2 3) '(3 4 5 6 7 8)))
|
|
102 | + (assert-equal '(2 2 1 3 4)
|
|
103 | + (union '(1 2 2 3) '(3 4)
|
|
104 | + :test #'eql))
|
|
105 | + (assert-equal '(2 2 1 3 4 5 6 7 8)
|
|
106 | + (union '(1 2 2 3) '(3 4 5 6 7 8)
|
|
107 | + :test #'eql))))
|
|
108 | + |
|
109 | +(define-test union.hash-eq
|
|
110 | + (:tag :issues)
|
|
111 | + (let ((lisp::*min-list-length-for-hashtable* 2))
|
|
112 | + (assert-equal '(b b a c d e)
|
|
113 | + (union '(a b b c) '(c d e) :test 'eq))
|
|
114 | + (assert-equal '(b b a c d e f g h)
|
|
115 | + (union '(a b b c) '(c d e f g h) :test 'eq))
|
|
116 | + (assert-equal '(b b a c d e)
|
|
117 | + (union '(a b b c) '(c d e) :test #'eq))
|
|
118 | + (assert-equal '(b b a c d e f g h)
|
|
119 | + (union '(a b b c) '(c d e f g h) :test #'eq))))
|
|
120 | + |
|
121 | +(define-test union.hash-equal
|
|
122 | + (:tag :issues)
|
|
123 | + (let ((lisp::*min-list-length-for-hashtable* 2))
|
|
124 | + (assert-equal '("b" "b" "a" "c" "d" "e")
|
|
125 | + (union '("a" "b" "b" "c")
|
|
126 | + '("c" "d" "e")
|
|
127 | + :test 'equal))
|
|
128 | + (assert-equal '("b" "b" "a" "c" "d" "e" "f" "g" "h")
|
|
129 | + (union '("a" "b" "b" "c")
|
|
130 | + '("c" "d" "e" "f" "g" "h")
|
|
131 | + :test 'equal))
|
|
132 | + (assert-equal '("b" "b" "a" "c" "d" "e")
|
|
133 | + (union '("a" "b" "b" "c")
|
|
134 | + '("c" "d" "e")
|
|
135 | + :test #'equal))
|
|
136 | + (assert-equal '("b" "b" "a" "c" "d" "e" "f" "g" "h")
|
|
137 | + (union '("a" "b" "b" "c")
|
|
138 | + '("c" "d" "e" "f" "g" "h")
|
|
139 | + :test #'equal))))
|
|
140 | + |
|
141 | +(define-test union.hash-equalp
|
|
142 | + (:tag :issues)
|
|
143 | + (let ((lisp::*min-list-length-for-hashtable* 2))
|
|
144 | + (assert-equal '("b" "b" "a" "C" "d" "e")
|
|
145 | + (union '("a" "b" "b" "c")
|
|
146 | + '("C" "d" "e")
|
|
147 | + :test 'equalp))
|
|
148 | + (assert-equal '("b" "b" "a" "c" "D" "e" "f" "g" "h")
|
|
149 | + (union '("a" "b" "b" "C")
|
|
150 | + '("c" "D" "e" "f" "g" "h")
|
|
151 | + :test 'equalp))
|
|
152 | + (assert-equal '("b" "b" "a" "C" "d" "e")
|
|
153 | + (union '("a" "b" "b" "c")
|
|
154 | + '("C" "d" "e")
|
|
155 | + :test #'equalp))
|
|
156 | + (assert-equal '("b" "b" "a" "c" "D" "e" "f" "g" "h")
|
|
157 | + (union '("a" "b" "b" "C")
|
|
158 | + '("c" "D" "e" "f" "g" "h")
|
|
159 | + :test #'equalp))))
|
|
160 | + |
|
161 | +;; Simple test that we handle a key correctly
|
|
162 | +(define-test union.hash-eql-with-key
|
|
163 | + (let ((lisp::*min-list-length-for-hashtable* 2))
|
|
164 | + (assert-equal '((3 "b") (2 "b") (1 "a") (4 "c") (5 "d"))
|
|
165 | + (union '((1 "a") (2 "b") (3 "b"))
|
|
166 | + '((1 "a") (4 "c") (5 "d"))
|
|
167 | + :key #'first))))
|
|
168 | + |
|
169 | +(define-test union.test-and-test-not
|
|
170 | + (assert-error 'simple-error
|
|
171 | + (union '(1 2)
|
|
172 | + '(3 4)
|
|
173 | + :test 'eql
|
|
174 | + :test-not 'eql))) |