[rucksack-devel] Re: rucksack-devel Digest, Vol 9, Issue 13
Cyrus Harmon
ch-rucksack at bobobeach.com
Mon Jan 15 21:34:26 UTC 2007
Ok, Kenny's email got me thinking. I think the code was working
before, but for reasons I didn't quite understand. The issue has to
do with the boundary conditions and how we do the splitting. In
particular, what happens when the key we are looking for falls in
between the last key of the left child and the first key of the right
child. I think it was working properly before, but this version is
perhaps a bit more explicit in ensuring that:
(defun find-subnode (btree node key)
"Returns the subnode that contains more information for the given
key."
;; Find the first binding with a key >= the given key and return
;; the corresponding subnode.
(let ((btree-key< (btree-key< btree))
(last (1- (btree-node-index-count node))))
(labels ((binary-search (start end)
(let* ((mid (+ start (ash (- end start) -1))))
(cond ((= start mid)
(let ((start-binding (node-binding node
start)))
(if (funcall btree-key< (binding-key start-
binding) key)
(binding-value (node-binding node end))
(binding-value start-binding))))
(t
(let ((mid-binding (node-binding node mid)))
(if (funcall btree-key< (binding-key mid-
binding) key)
(binary-search mid end)
(binary-search start mid))))))))
(if (funcall btree-key< (binding-key (node-binding node (1-
last))) key)
(binding-value (node-binding node last))
(binary-search 0 last))))
;;; this is the old (linear search) version kept here for reference
;;; for the moment
#+nil
(progn
(loop with btree-key< = (btree-key< btree)
with last-index = (1- (btree-node-index-count node))
for i to last-index
for binding = (node-binding node i)
when (or (= i last-index)
(funcall btree-key< key (binding-key binding))
(not (funcall btree-key< (binding-key binding) key)))
do (return-from find-subnode (binding-value binding)))
(error "This shouldn't happen.")))
(defun find-binding-in-node (key node btree)
(let ((btree-key< (btree-key< btree))
(array (btree-node-index node))
(index-count (btree-node-index-count node)))
(labels ((binary-search (start end)
(let* ((mid (+ start (ash (- end start) -1))))
(cond ((= start mid)
(let ((start-binding (p-aref array start)))
(if (funcall btree-key< (binding-key start-
binding) key)
(when (< end index-count)
(p-aref array end))
start-binding)))
(t (let ((mid-binding (p-aref array mid)))
(if (funcall btree-key< (binding-key mid-
binding) key)
(binary-search mid end)
(binary-search start mid))))))))
(when (plusp index-count)
(let ((candidate (binary-search 0 index-count)))
(when (and candidate
(funcall (btree-key= btree) (binding-key
candidate) key))
candidate)))))
;;; this is the old (linear search) version kept here for reference
;;; for the moment
#+nil
(let ((index-count (btree-node-index-count node)))
(and (plusp index-count)
(loop with array = (btree-node-index node)
with btree-key< = (btree-key< btree)
for i from 0 below index-count
for candidate = (p-aref array i)
for candidate-key = (binding-key candidate)
while (funcall btree-key< candidate-key key)
finally (when (funcall (btree-key= btree) key candidate-
key)
(return candidate))))))
Cyrus
On Jan 15, 2007, at 9:08 AM, Ken Tilton wrote:
>> On Jan 14, 2007, at 3:10 PM, Cyrus Harmon wrote:
>>
>>> On Jan 14, 2007, at 3:02 PM, Arthur Lemmens wrote:
>>>
>>>> Cyrus Harmon wrote:
>>>>
>>>>
>>>>
>>>>> + (if (not (funcall btree-key< (binding-
>>>>> key mid-binding) key))
>>>>> + (binary-search start mid)
>>>>> + (binary-search mid end))))))
>>>>>
>>>> Same here.
>>>>
>>> ditto
>>>
>>
>> hmm... should that be (binary-search (1+ mid) end) ?
>>
> Not if it is traditionally Lispy:
>
> (let ((s "abc123")
> (m 3))
> (list (subseq s 0 m)(subseq s m))) -> "abc123"
>
> kt
More information about the rucksack-devel
mailing list