Skip to content

Instantly share code, notes, and snippets.

@uupaa
Last active August 29, 2015 14:10
Show Gist options
  • Save uupaa/efe5137ef99f4b2d1438 to your computer and use it in GitHub Desktop.
Save uupaa/efe5137ef99f4b2d1438 to your computer and use it in GitHub Desktop.
Math.imul

こちらは、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 >>> 0v1 & 0xffffffffしなければならないですし
(ε・◇・)з その速度的なそのペナルティや、
(ε・◇・)з 余計なコードが入って、元のコードから乖離する事を考えたら…ね?
(ε・◇・)з あと… JIT コンパイラがちょっと頑張れば解決するような、ささいな問題なので
(ε・◇・)з 気にしないほうがいいです

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment