Skip to content
Snippets Groups Projects
Commit ada02b06 authored by Nikodemus Siivola's avatar Nikodemus Siivola
Browse files

faster WHICHEVER

 Call RANDOM just once, and build an inline binary search tree
 for O(log n) goodness instead of O(n).

 Patch by: Gustavo <gugamilare@gmail.com>
parent d4a72df5
No related branches found
No related tags found
No related merge requests found
...@@ -52,15 +52,20 @@ returns the values of DEFAULT if no keys match." ...@@ -52,15 +52,20 @@ returns the values of DEFAULT if no keys match."
(setf possibilities (mapcar (lambda (p) (macroexpand p env)) possibilities)) (setf possibilities (mapcar (lambda (p) (macroexpand p env)) possibilities))
(if (every (lambda (p) (constantp p)) possibilities) (if (every (lambda (p) (constantp p)) possibilities)
`(svref (load-time-value (vector ,@possibilities)) (random ,(length possibilities))) `(svref (load-time-value (vector ,@possibilities)) (random ,(length possibilities)))
(with-gensyms (function) (labels ((expand (possibilities position random-number)
`(let ((,function (lambda () ,(pop possibilities)))) (if (null (cdr possibilities))
(declare (function ,function)) (car possibilities)
,@(let ((p 1)) (let* ((length (length possibilities))
(mapcar (lambda (possibility) (half (truncate length 2))
`(when (zerop (random ,(incf p))) (second-half (nthcdr half possibilities))
(setf ,function (lambda () ,possibility)))) (first-half (butlast possibilities (- length half))))
possibilities)) `(if (< ,random-number ,(+ position half))
(funcall ,function))))) ,(expand first-half position random-number)
,(expand second-half (+ position half) random-number))))))
(with-gensyms (random-number)
(let ((length (length possibilities)))
`(let ((,random-number (random ,length)))
,(expand possibilities 0 random-number)))))))
(defmacro xor (&rest datums) (defmacro xor (&rest datums)
"Evaluates its argument one at a time, from left to right. If more then one "Evaluates its argument one at a time, from left to right. If more then one
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment