正の fixnum から符号位置に少しシフトする方法を探しています。基本的に、私が望むのは、オーバーフロー チェックなしで fixnum 左シフトを実行する予測可能な (未定義ではない) 方法です。
非効率的な実装は次のようになります。
(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
理想的には、これは単一の CPU 命令にコンパイルされます (少なくとも定数シフトの場合。レジスタと同じ幅またはそれより広いシフトを処理する方法が CPU によって異なります)。