int64-buffer という 64 ビット整数を扱うモジュールを書いていて、8 バイト長の符号あり整数の符号を反転する JavaScript コードを書いてました。
前提:Buffer とか Uint8Array のビッグエンディアンのバイト列に整数値を格納していて、最初のバイトの最上位ビットが符号であること。
function neg(buffer, start, end) {
var p = 1;
for (var i = end; i >= start; i--) {
var q = (buffer[i] ^ 255) + p;
p = (q > 255) ? 1 : 0;
buffer[i] = p ? 0 : q;
}
}
メモ:
- 要は、すべてのビットを反転させて、1 を足せばよい。
- 引数で start、end を指定できるのは、バッファ上の位置を指定できるようにするため。
- 0 の符号を判定したときは 0 のままになる。
- 0x80000000 (INT32_MIN) などのそのバイト数で表せる最小の負の値の符号を反転したいときは、反転できないので、そのままになる。(C 言語だとそういう動作になっていた)
-
p
の値は 0 か 1 のみ。q
の値は 0〜255。