I'm looking for a way to shift a bit from a positive fixnum into the sign position. Basically, what I want is a predictable (not undefined) way to perform a fixnum left shift without overflow checks.
An inefficient implementation looks like this:
(define shift-left
(lambda (value shift)
(let ([unsigned-to-signed
(lambda (value width)
(let* ([sign-mask (bitwise-arithmetic-shift-left
1 (- width 1))]
[sign (bitwise-and value sign-mask)])
(bitwise-ior
(bitwise-bit-field value 0 width)
(- sign))))])
(unsigned-to-signed
(bitwise-arithmetic-shift-left value shift)
(fixnum-width)))))
(shift-left 1 59) ⇒ 576460752303423488
(shift-left 1 60) ⇒ -1152921504606846976
(shift-left 1 61) ⇒ 0
Ideally, this would compile down to a single CPU instruction (at least for constant shifts; CPUs differ in the way treat shifts as wide as the register or wider).
IN scheme it won't work unless you look for implementation defined features.
In scheme it's standardized the tower of arithmetic types which makes very inconvenient for you to control the inner sides of number representations.
What you try to do makes sense only if you understand the internals of some implementation, otherwise you waste your time.