-
Notifications
You must be signed in to change notification settings - Fork 0
Home
uupaa edited this page Apr 21, 2016
·
38 revisions
Bit.js is a JavaScript library that supports the analysis of binary data. It aggregates the low-level bit manipulation functions.
(Bit.js はバイナリデータのパースなど、低レベルなビット操作関数を集約したライブラリです)
// get contiguous n bits (bit shift and mask).
// 連続したnビットを取り出します
Bit.n(0x000000ff, 0b00000000000000000000000011111100) // -> 0x3f,
Bit.n(0x000000ff, 0b00000000000000000000000011000000) // -> 0x03,
// bit split by bit-pattern
// Bit.splitN を使うとビットパターンを切り出せます
// 戻り値の先頭には第一引数の値がそのまま格納されています
Bit.split32(0xffff1234, [16,4,4,4,4]) // -> [0xffff, 0x1, 0x2, 0x3, 0x4]
// 16 4 4 4 4 bit
Bit.split24(0xff1234, [16,4,4]) // -> [0xff, 0x1, 0x2, 0x3, 0x4]
Bit.split16(0x1234, [8,8]) // -> [0x12, 0x34]
Bit.split8(0xfe, [2,2,4]) // -> [0x3, 0x3, 0xe]
// With ES6 Destructuring Assignment
// ES6 Destructuring Assignment と Bit.splitN を併用すると以下のように簡便に記述できます
var [a, b, c] = Bit.split32(0x00001234, [16, 8, 8]);
// -> a = 0x12, b = 0x3, c = 0x4
// population count (counting 1 bits)
// 1のビットの数を数えます
Bit.popcnt(0x6) // -> 2
// count the number of contiguous 1 bits from Left-side or Right-side
// 連続した1のビットの数を左方向または右方向から数えます
Bit.cnl(0b11001110) // -> 2
Bit.cnr(0b11001110) // -> 3
// Number of Leading Zero
Bit.nlz(0x6) // -> 29
Bit.clz(0x6) // -> 29 (this function is an alias of Bit.nlz)
// Number of Training Zero
Bit.ntz(0x6) // -> 1
Bit.ctz(0x6) // -> 1 (this function is an alias of Bit.ntz)
// binary dump
// Bit.dump を使うとビットパターンをダンプできます
Bit.dump(0x12345678, [4,4,8,4,4,8]);
// -> "0001, 0010, 00110100, 0101, 0110, 01111000"
// verbose dump
// 第三引数(verbose) を true にすると情報量が増えます
Bit.dump(0x12345678, bitPattern, true);
// -> "00010010001101000101011001111000(0x12345678), 0001(1,0x1), 0010(2,0x2), 00110100(52,0x34), 0101(5,0x5), 0110(6,0x6), 01111000(120,0x78)"
// 0x12345678 の2進数表現 (10進数,16進数)
// get IEEE754 expression
// Bit.IEEE754 を使うと数値の IEEE754 表現を取得できます
var doublePrecision = true;
var u32array = Bit.IEEE754(0.15625, doublePrecision);
Bit.dump(u32array[0], [1,11,20]) + Bit.dump(u32array[1], [32])
// -> "0, 01111111100, 0100000000000000000000000000000000000000000000000000"
// BitView
// BitView を使うとバイナリデータ、特にビットで圧縮されたヘッダ部分を簡単にパースできます
var bitView = new BitView(new Uint8Array([0, 1, 2, 3, 0xFF, 0xFE, 0xFD, 0xFC]));
// read 32 bit
bitView.u(32) // -> 0x00010203
// read 24 bit
bitView.u(24) // -> 0xFFFEFD
// read 1 bit
bitView.u(1) // -> 0x1 `11111100` (0xFC)
// ~
// read 2 bit
bitView.u(2) // -> 0x3 `11111100` (0xFC)
// ~~
// read 5 bit
bitView.u(5) // -> 0x1C `11111100` (0xFC)
// ~~~~~開発初期段階においては Bit.splitN や Bit.dump を使い、ザクザクと記述していきます。
ある程度実装が落ち着いたら、ベンチマークを取得し、特に効果的がある部分は、 Bit.n や直接ビット演算で書き直すとよいでしょう。
// --- 開発中のコード(最適前の状態) ---
var u16 = 0xffee;
var bits = Bit.split16(u16, [1, 1, 1, 13]);
var a = bits[0]; // -> 1
var b = bits[1]; // -> 1
var c = bits[2]; // -> 1
var d = bits[3]; // -> 0x1fee
// --- Bit.n を使うことで可読性を維持しつつ程々に最適化したコード ---
var u16 = 0xffee;
var a = Bit.n(u16, 0b1000000000000000); // -> 1
var b = Bit.n(u16, 0b0100000000000000); // -> 1
var c = Bit.n(u16, 0b0010000000000000); // -> 1
var d = Bit.n(u16, 0b0001111111111111); // -> 0x1fee
// --- 実行速度最適化を施したコード(可読性は下がっています) ---
var u16 = 0xffee;
var a = u16 >>> 15 & 0x1; // -> 1
var b = u16 >>> 14 & 0x1; // -> 1
var c = u16 >>> 13 & 0x1; // -> 1
var d = u16 >>> 0 & 0x1fff; // -> 0x1fee また、DevTools の watch式 やコンソールに Bit.dump の結果を表示しつつ実装をすすめると良いでしょう。
ES6 の Destructuring Assignment が使える環境では、さらに簡単に記述できるようになります。
var u16 = 0x0000ffee
var [a, b, c, d] = Bit.split16(u16, [1, 1, 1, 13]);
// a = 0x1, b = 0x1, c = 0x1, d = 0x1fee