argumentcomputer/lurk-beta

expose minimal bit operations

porcuquine opened this issue · 0 comments

It's great that we can get a handle on the underlying bit decomposition through trickery like this:

commit: 2024-02-13 1d4d308e2bc12f5ab431ea210c0b722f9eb31825
Lurk REPL welcomes you.
user> !(def odd? (lambda (x) (< (/ x 2) 0)))
odd?
user> (odd? 3)
[9 iterations] => t
user> (odd? 2)
[9 iterations] => nil

But even if inlined manually (which is pretty cryptic), this costs 6 iterations.

user> (< (/ 3 2) 0)
[6 iterations] => t
user> (< (/ 2 2) 0)
[6 iterations] => nil

Given that the Lurk reduction performs the bit decomposition anyway, it should be very cheap to make this available directly. This is not an idle consideration because iterating bits is an important operation. For example:

(letrec ((odd? (lambda (x) (< (/ x 2) 0)))
         (fastexp (lambda (b e)
                    (if (= e 0)
                        1
                        (if (odd? e)
                            (* b (fastexp (* b b) (/ (- e 1) 2)))
                            (fastexp (* b b) (/ e 2)))))))
  (fastexp 3 3))

We could just implement odd?, which would be cheap and yield high value. This might not be the globally best answer, but it's an obvious and simple way to solve the immediate problem at hand.

A complementary idea that might be useful in slightly different circumstances would to just return the value of the least-significant bit, as a Num and/or u64. Implementing both would be annoying, and it's probably enough to just use u64 — since that will behave 'as if' a Num when used in such a context. Extending that logic to consider future UInt types, I suppose the natural thing do here would be to return a U1 — which we obviously don't currently have.

For now, I think just implementing odd? would be valuable.