Raymond Toy pushed to branch issue-240-subsetp-with-hash-table at cmucl / cmucl
Commits:
-
f577eda6
by Raymond Toy at 2023-07-23T22:38:00+00:00
-
0411c386
by Raymond Toy at 2023-07-23T22:38:01+00:00
-
3e8b0a12
by Raymond Toy at 2023-07-26T13:43:15+00:00
-
24152f4d
by Raymond Toy at 2023-07-26T13:43:15+00:00
-
5b27393f
by Carl Shapiro at 2023-07-30T21:15:48-07:00
-
a7300f03
by Carl Shapiro at 2023-07-31T05:28:58+00:00
-
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
-
d22817cb
by Raymond Toy at 2023-08-16T09:28:39-07:00
-
a4c90a8b
by Raymond Toy at 2023-08-16T12:52:55-07:00
9 changed files:
- benchmarks/cl-bench/files/math.lisp
- bin/clean-target.sh
- bin/make-extra-dist.sh
- src/code/c-call.lisp
- src/code/list.lisp
- src/compiler/seqtran.lisp
- src/general-info/release-21f.md
- + tests/list.lisp
- tests/run-tests.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)
|
| ... | ... | @@ -48,10 +48,10 @@ CORE='-o -name "*.core"' |
| 48 | 48 | |
| 49 | 49 | if [ -n "$KEEP" ]; then
|
| 50 | 50 | case $KEEP in
|
| 51 | - lib) GREP='egrep -v'
|
|
| 51 | + lib) GREP='grep -Ev'
|
|
| 52 | 52 | PATTERN='(gray-streams|gray-compat|simple-streams|iodefs|external-formats|clx|hemlock|clm)-library' ;;
|
| 53 | 53 | core) CORE='' ;;
|
| 54 | - all) GREP='egrep -v'
|
|
| 54 | + all) GREP='grep -Ev'
|
|
| 55 | 55 | PATTERN='(gray-streams|gray-compat|simple-streams|iodefs|external-formats|clx|hemlock|clm)-library|(asdf|defsystem)'
|
| 56 | 56 | CORE='' ;;
|
| 57 | 57 | esac
|
| ... | ... | @@ -94,12 +94,12 @@ install ${GROUP} ${OWNER} -m 0755 $TARGET/motif/server/motifd \ |
| 94 | 94 | |
| 95 | 95 | # Install the contrib stuff. Create the directories and then copy the files.
|
| 96 | 96 | |
| 97 | -for d in `(cd src; find contrib -type d -print | egrep -v "CVS|asdf|defsystem")`
|
|
| 97 | +for d in `(cd src; find contrib -type d -print | grep -E -v "CVS|asdf|defsystem")`
|
|
| 98 | 98 | do
|
| 99 | 99 | install -d ${GROUP} ${OWNER} -m 0755 $DESTDIR/lib/cmucl/lib/$d
|
| 100 | 100 | done
|
| 101 | 101 | |
| 102 | -for f in `(cd src/contrib; find . -type f -print | egrep -v "CVS|asdf|defsystem|unix")`
|
|
| 102 | +for f in `(cd src/contrib; find . -type f -print | grep -E -v "CVS|asdf|defsystem|unix")`
|
|
| 103 | 103 | do
|
| 104 | 104 | FILE=`basename $f`
|
| 105 | 105 | DIR=`dirname $f`
|
| ... | ... | @@ -108,13 +108,13 @@ done |
| 108 | 108 | |
| 109 | 109 | # Install all the locale data.
|
| 110 | 110 | |
| 111 | -for d in `(cd src/i18n/; find locale -type d -print | egrep -v CVS)`
|
|
| 111 | +for d in `(cd src/i18n/; find locale -type d -print | grep -E -v CVS)`
|
|
| 112 | 112 | do
|
| 113 | 113 | install -d ${GROUP} ${OWNER} -m 0755 $DESTDIR/lib/cmucl/lib/$d
|
| 114 | 114 | done
|
| 115 | 115 | |
| 116 | 116 | # Install mo files.
|
| 117 | -for f in `(cd $TARGET/i18n; find locale -type f -print | egrep -v 'CVS|~.*~|.*~')`
|
|
| 117 | +for f in `(cd $TARGET/i18n; find locale -type f -print | grep -E -v 'CVS|~.*~|.*~')`
|
|
| 118 | 118 | do
|
| 119 | 119 | FILE=`basename $f`
|
| 120 | 120 | DIR=`dirname $f`
|
| ... | ... | @@ -122,7 +122,7 @@ do |
| 122 | 122 | done
|
| 123 | 123 | |
| 124 | 124 | # Install po files. (Do we really need to distribute the po files?)
|
| 125 | -#for f in `(cd $TARGET/i18n; find locale -type f -print | egrep -v 'CVS|~.*~|.*~')`
|
|
| 125 | +#for f in `(cd $TARGET/i18n; find locale -type f -print | grep -E -v 'CVS|~.*~|.*~')`
|
|
| 126 | 126 | #do
|
| 127 | 127 | # FILE=`basename $f`
|
| 128 | 128 | # DIR=`dirname $f`
|
| ... | ... | @@ -19,7 +19,7 @@ |
| 19 | 19 | |
| 20 | 20 | (intl:textdomain "cmucl")
|
| 21 | 21 | |
| 22 | -(export '(char short int long long-long unsigned-char unsigned-short unsigned-int
|
|
| 22 | +(export '(char short int long long-long signed-char unsigned-char unsigned-short unsigned-int
|
|
| 23 | 23 | unsigned-long unsigned-long-long float double c-string void))
|
| 24 | 24 |
|
| 25 | 25 | |
| ... | ... | @@ -30,6 +30,8 @@ |
| 30 | 30 | (def-alien-type int (integer 32))
|
| 31 | 31 | (def-alien-type long (integer #-alpha 32 #+alpha 64))
|
| 32 | 32 | (def-alien-type long-long (integer 64))
|
| 33 | +;; The same as c-call:char, for convenience with C signed-char.
|
|
| 34 | +(def-alien-type signed-char (integer 8))
|
|
| 33 | 35 | |
| 34 | 36 | (def-alien-type unsigned-char (unsigned 8))
|
| 35 | 37 | (def-alien-type unsigned-short (unsigned 16))
|
| ... | ... | @@ -749,15 +749,9 @@ |
| 749 | 749 | (defparameter *min-list-length-for-hashtable*
|
| 750 | 750 | 15)
|
| 751 | 751 | |
| 752 | -(defparameter *allow-hashtable-for-set-functions*
|
|
| 753 | - nil)
|
|
| 754 | - |
|
| 755 | 752 | ;; Convert a list to a hashtable. The hashtable does not handle
|
| 756 | 753 | ;; duplicated values in the list. Returns the hashtable.
|
| 757 | 754 | (defun list-to-hashtable (list key test test-not)
|
| 758 | - (unless *allow-hashtable-for-set-functions*
|
|
| 759 | - (return-from list-to-hashtable nil))
|
|
| 760 | - |
|
| 761 | 755 | ;; Don't currently support test-not when converting a list to a hashtable
|
| 762 | 756 | (unless test-not
|
| 763 | 757 | (let ((hash-test (let ((test-fn (if (and (symbolp test)
|
| ... | ... | @@ -979,17 +973,25 @@ |
| 979 | 973 | (rplacd splicex (cdr x)))
|
| 980 | 974 | (setq splicex x)))))
|
| 981 | 975 | |
| 976 | +(defvar *allow-hashtable-for-set-functions* t)
|
|
| 977 | + |
|
| 982 | 978 | (defun subsetp (list1 list2 &key key (test #'eql testp) (test-not nil notp))
|
| 983 | 979 | "Returns T if every element in list1 is also in list2."
|
| 984 | 980 | (declare (inline member))
|
| 985 | 981 | (when (and testp notp)
|
| 986 | 982 | (error "Test and test-not both supplied."))
|
| 987 | 983 | |
| 988 | - (let ((hashtable (list-to-hashtable list2 key test test-not)))
|
|
| 984 | + ;; SUBSETP is used early in TYPE-INIT where hash tables aren't
|
|
| 985 | + ;; available yet, so we can't use hashtables then. LISPINIT will
|
|
| 986 | + ;; take care to disable this for the kernel.core. SAVE will set
|
|
| 987 | + ;; this to true it's safe to use hash tables for SUBSETP.
|
|
| 988 | + (let ((hashtable (when *allow-hashtable-for-set-functions*
|
|
| 989 | + (list-to-hashtable list2 key test test-not))))
|
|
| 989 | 990 | (cond (hashtable
|
| 990 | 991 | (dolist (item list1)
|
| 991 | 992 | (unless (nth-value 1 (gethash (apply-key key item) hashtable))
|
| 992 | - (return-from subsetp nil))))
|
|
| 993 | + (return-from subsetp nil)))
|
|
| 994 | + t)
|
|
| 993 | 995 | ((null hashtable)
|
| 994 | 996 | (dolist (item list1)
|
| 995 | 997 | (unless (with-set-keys (member (apply-key key item) list2))
|
| ... | ... | @@ -1110,7 +1112,10 @@ |
| 1110 | 1112 | (setf (car l) (cdar l)))
|
| 1111 | 1113 | (setq res (apply function (nreverse args)))
|
| 1112 | 1114 | (case accumulate
|
| 1113 | - (:nconc (setq temp (last (nconc temp res))))
|
|
| 1115 | + (:nconc (when res
|
|
| 1116 | + (let ((next-temp (last res)))
|
|
| 1117 | + (rplacd temp res)
|
|
| 1118 | + (setq temp next-temp))))
|
|
| 1114 | 1119 | (:list (rplacd temp (list res))
|
| 1115 | 1120 | (setq temp (cdr temp)))))))
|
| 1116 | 1121 |
| ... | ... | @@ -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)))
|
| ... | ... | @@ -25,6 +25,7 @@ public domain. |
| 25 | 25 | * ~~#154~~ piglatin translation does not work anymore
|
| 26 | 26 | * ~~#171~~ Readably print `(make-pathname :name :unspecfic)`
|
| 27 | 27 | * ~~#242~~ Fix bug in `alien-funcall` with `c-call:char` as result type
|
| 28 | + * ~~#244~~ Add `c-call:signed-char`
|
|
| 28 | 29 | * ~~#248~~ Print MOVS instruction with correct case
|
| 29 | 30 | * Other changes:
|
| 30 | 31 | * Improvements to the PCL implementation of CLOS:
|
| 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)))) |
| ... | ... | @@ -110,9 +110,10 @@ |
| 110 | 110 | (format t " ~5D tests failed~%" failed)
|
| 111 | 111 | (format t " ~5D tests with execution errors~%" execute-errors)
|
| 112 | 112 | (format t "~5,3f% of the tests passed~%"
|
| 113 | - (float (* 100
|
|
| 114 | - (- 1 (/ (+ failed execute-errors)
|
|
| 115 | - (+ passed failed execute-errors))))))
|
|
| 113 | + (let ((total (+ passed failed execute-errors)))
|
|
| 114 | + (if (zerop total)
|
|
| 115 | + 0.0
|
|
| 116 | + (* 100.0 (- 1.0 (/ (- total passed) total))))))
|
|
| 116 | 117 | ;; Print some info about any failed tests. Then exit. We want to
|
| 117 | 118 | ;; set the exit code so that any scripts runnning this can
|
| 118 | 119 | ;; determine if there were any test failures.
|