-
Notifications
You must be signed in to change notification settings - Fork 5
/
test-binsearch.lisp
63 lines (58 loc) · 2.67 KB
/
test-binsearch.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
(defun meas-binsearch (low-index hi-index compare-fn)
(declare (type fixnum low-index hi-index))
;; General utility binary search routine.
;; low-index = starting index of table, high-index is 1 beyond table's last index.
;; compare-fn is a user provided comparison routine of one argument, the index,
;; and it should return <0, =0, >0 for each index.
;; returns: found, ixu
;;
;; When found is true, ixu is its index location
;; When found is false, ixu is where it would have to be inserted for key < key[ixu]
;; each index. Routine stops when comparison yields 0, or when the table is exhausted.
;; Comparison values of <0 indicate that the index is too high, >0 indicates it is too low.
;;
(um:perform search ((ixl (1- low-index))
(ixu hi-index)
(iter 1))
(declare (type fixnum ixl ixu))
(cond ((> (- ixu ixl) 1)
(let* ((ixm (truncate (+ ixu ixl) 2))
(c (funcall compare-fn ixm)))
(declare (type fixnum ixm c))
(cond ((= c 0) (values iter t ixm)) ;; found it!
((< c 0) (search ixl ixm (1+ iter)))
(t (search ixm ixu (1+ iter)))
)))
(t (values iter nil ixu))
)))
(defun tst (n)
(format t "~&Table length: ~D~%" n)
(let ((tbl (make-array n :initial-contents (loop for ix from 0 below n collect ix)))
(arr (make-array 20 :initial-element 0))
(niter 1000000))
(loop for ix from 1 to niter do
(let ((key (lw:mt-random (* 1 n))))
(incf (aref arr (meas-binsearch 0 n (lambda (jx) (- key (aref tbl jx))))))))
(plt:plot 'plt1
(map 'vector (let ((sum 0))
(lambda (v)
(incf sum (/ v niter))))
(subseq arr 0 (+ 2 (position-if (complement 'zerop) arr
:from-end t))))
:title (format nil "Binary Search for Table Size = ~D" n)
:xtitle "Number of Iterations"
:ytitle "Cumulative Fraction"
:clear t
:thick 2
:line-type :stepped)
(plt:plot 'plt2
(map 'vector (lambda (v)
(/ v niter))
(subseq arr 0 (+ 2 (position-if (complement 'zerop) arr
:from-end t))))
:title (format nil "Binary Search for Table Size = ~D" n)
:xtitle "Number of Iterations"
:ytitle "Fraction"
:clear t
:thick 2
:line-type :stepped)))