[cl-utilities-cvs] CVS update: cl-utilities/extremum.lisp

Peter Scott pscott at common-lisp.net
Thu May 12 21:17:23 UTC 2005


Update of /project/cl-utilities/cvsroot/cl-utilities
In directory common-lisp.net:/tmp/cvs-serv18708

Modified Files:
	extremum.lisp 
Log Message:
Improved efficiency some. Added EXTREMUM-FASTKEY which uses a
different, and sometimes faster, algorithm.

Date: Thu May 12 23:17:23 2005
Author: pscott

Index: cl-utilities/extremum.lisp
diff -u cl-utilities/extremum.lisp:1.1.1.1 cl-utilities/extremum.lisp:1.2
--- cl-utilities/extremum.lisp:1.1.1.1	Mon May  9 23:26:29 2005
+++ cl-utilities/extremum.lisp	Thu May 12 23:17:23 2005
@@ -13,6 +13,15 @@
                     a
                     b)))
 
+(defun zero-length-p (sequence)
+  "Is the length of SEQUENCE equal to zero?"
+  (declare (optimize (speed 3) (safety 0) (space 0) (debug 1)))
+  (or (null sequence)
+      (when (vectorp sequence)
+	(zerop (length sequence)))))
+
+(declaim (inline zero-length-p))
+
 ;; This is an extended version which takes START and END keyword
 ;; arguments. Any spec-compliant use of EXTREMUM will also work with
 ;; this extended version.
@@ -23,7 +32,7 @@
 http://www.cliki.net/EXTREMUM for the full
 specification. Additionally, START and END specify the beginning and
 ending indices of the part of the sequence we should look at."
-  (if (= 0 (length sequence))
+  (if (zero-length-p sequence)
       (restart-case (error 'no-extremum)
 	(continue ()
 	  :report "Return NIL instead"
@@ -37,9 +46,44 @@
   "Returns the element of SEQUENCE that would appear first if the
 sequence were ordered according to SORT using PREDICATE and KEY. See
 http://www.cliki.net/EXTREMUM for the full specification."
-  (if (= 0 (length sequence))
+  (if (zero-length-p sequence)
+      (restart-case (error 'no-extremum)
+	(continue ()
+	  :report "Return NIL instead"
+	  nil))
+      (reduce (comparator predicate key) sequence)))
+
+;; This is an "optimized" version which calls KEY less. REDUCE is
+;; already so optimized that this will actually be slower unless KEY
+;; is expensive. And on CLISP, of course, the regular version will be
+;; much faster since built-in functions are ridiculously faster than
+;; ones implemented in Lisp. Be warned, this isn't as carefully tested
+;; as regular EXTREMUM and there's more that could go wrong.
+(defun extremum-fastkey (sequence predicate
+			 &key (key #'identity) (start 0) end)
+  "EXTREMUM implemented so that it calls KEY less. This is only faster
+if the KEY function is so slow that calling it less often would be a
+significant improvement; ordinarily it's slower."
+  (declare (optimize (speed 3) (safety 0) (space 0) (debug 1)))
+  (if (zero-length-p sequence)
       (restart-case (error 'no-extremum)
 	(continue ()
 	  :report "Return NIL instead"
 	  nil))
-      (reduce (comparator predicate key) sequence)))
\ No newline at end of file
+      (let* ((smallest (elt sequence 0))
+	     (smallest-key (funcall key smallest))
+	     (current-index 0)
+	     (real-end (or end #.(1- most-positive-fixnum))))
+	(declare (type (integer 0 #.most-positive-fixnum)
+		       current-index real-end start))
+	(map nil #'(lambda (x)
+		     (when (<= start current-index real-end)
+		       (let ((x-key (funcall key x)))
+			 (when (funcall predicate
+					x-key
+					smallest-key)
+			   (setf smallest x)
+			   (setf smallest-key x-key))))
+		     (incf current-index))
+	     sequence)
+	smallest)))
\ No newline at end of file




More information about the Cl-utilities-cvs mailing list