OCaml の Pervasives にはシフト演算子として (lsl), (lsr), (asr) があります。 ところで OCaml の整数は GC のために末尾の 1 bit を使っています。 そこで OCaml のシフト演算子はこのビットを一旦退避させてから計算しています。 この記事ではその部分の実装をメモっておきます。

環境: OCaml 4.07.0

とりあえず Pervasives の実装を見てみると以下のように書かれています。

(* stdlib/pervasives.ml より引用 *)
external ( lsl ) : int -> int -> int = "%lslint"
external ( lsr ) : int -> int -> int = "%lsrint"
external ( asr ) : int -> int -> int = "%asrint"

external というのは外部実装に任せますということです。その外部実装には以下のように書かれています。マクロがありますが気分で読めます。

/* runtime/interp.c より引用 */
Instruct(LSLINT):
  accu = (value)((((intnat) accu - 1) << Long_val(*sp++)) + 1); Next;
Instruct(LSRINT):
  accu = (value)((((uintnat) accu) >> Long_val(*sp++)) | 1); Next;
Instruct(ASRINT):
  accu = (value)((((intnat) accu) >> Long_val(*sp++)) | 1); Next;

※この記事は、大昔に書いたメモが出てきたので情報をアップデートして公開したものです。