Commit ada02b06 authored by Nikodemus Siivola's avatar Nikodemus Siivola
Browse files


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

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