こちらは、shibukawa さんのエントリ へのアンサー・ソング的な何かです。
Math.imul を使うと、C言語のコードを原型を維持したまま JavaScript に変換することができます。
これにより、派生版の実装がだんだんC言語版から取り残されていく(Box2D的な残念な)現象を最小限にできるのではないでしょうか。
高速なHash関数 xxhash.c を JavaScript に変換した WMXXHash.js を例に説明するとこのようになります。
若干のコーディングスタイルの変化(JSHint対策)や、UINT32 な変数を5個作り出すために new Uint32Array(5) を使うというアイデアが入っていますが、変数名などは基本的にC言語のコードのままにしてあります。
Math.imul が利用できない環境では、以下の polyfill を利用します。
//{@es6_polyfill
function es6_polyfill_math_imul(a, // @arg Uint32|Uint64 - value a
b) { // @arg Uint32|Uint64 - value b
// @ret Uint32 - the C-like 32-bit multiplication of the two parameters.
var a_high = (a >>> 16) & 0xffff;
var a_low = a & 0xffff;
var b_high = (b >>> 16) & 0xffff;
var b_low = b & 0xffff;
return ((a_low * b_low) + (((a_high * b_low + a_low * b_high) << 16) >>> 0)|0);
}
//}@es6_polyfill
{@es6_polyfill ... }@es6_polyfill
は、WebModule の $ npm run build
コマンドでコンパイルする時に、プリプロセッサフェーズでコードブロックをごっそり削除できるようにつけています。
(ε・◇・)з これどういう事かとという
(ε・◇・)з polyfill は基本的に数年後には要らないコードになるので、
(ε・◇・)з その時に削れるようにマークアップしてあります。という意味です。
(ε・◇・)з 場当たり的なコードを、はがせない形で本流に組み込むのは、クソコード化の始まりなのです
心配性な方は、「new Uint32Array(5) で作成した配列へのアクセスが速度に影響する… のでは?」と思われると思います… が
(ε・◇・)з 普通の IEEE754 なローカル変数(Number型)を使うよりはマシかなと
(ε・◇・)з Number型だと、演算後に毎回v1 >>> 0
やv1 & 0xffffffff
しなければならないですし
(ε・◇・)з その速度的なそのペナルティや、
(ε・◇・)з 余計なコードが入って、元のコードから乖離する事を考えたら…ね?
(ε・◇・)з あと… JIT コンパイラがちょっと頑張れば解決するような、ささいな問題なので
(ε・◇・)з 気にしないほうがいいです